on master help sign in
.git-blame-ignore-revsnew file+2
since splitsnapshots
unifiedsplit
@@ -0,0 +1,2 @@
1+# Move code into subdirectories
2+bf1ac1bad848bb2c081f0cae1631bf53811ec05a
.github/workflows/haskell-ci-bench.ymlnew file+241
@@ -0,0 +1,241 @@
1+# This GitHub workflow config has been generated by a script via
2+#
3+# haskell-ci 'github' '--project' 'cabal.bench.project' '-o' '.github/workflows/haskell-ci-bench.yml' '--github-action-name' 'Benchmarks'
4+#
5+# To regenerate the script (for example after adjusting tested-with) run
6+#
7+# haskell-ci regenerate
8+#
9+# For more information, see https://github.com/haskell-CI/haskell-ci
10+#
11+# version: 0.19.20240702
12+#
13+# REGENDATA ("0.19.20240702",["github","--project","cabal.bench.project","-o",".github/workflows/haskell-ci-bench.yml","--github-action-name","Benchmarks"])
14+#
15+name: Benchmarks
16+on:
17+ push:
18+ branches:
19+ - master
20+ pull_request:
21+ branches:
22+ - master
23+jobs:
24+ linux:
25+ name: Benchmarks - Linux - ${{ matrix.compiler }}
26+ runs-on: ubuntu-20.04
27+ timeout-minutes:
28+ 60
29+ container:
30+ image: buildpack-deps:jammy
31+ continue-on-error: ${{ matrix.allow-failure }}
32+ strategy:
33+ matrix:
34+ include:
35+ - compiler: ghc-9.10.1
36+ compilerKind: ghc
37+ compilerVersion: 9.10.1
38+ setup-method: ghcup
39+ allow-failure: false
40+ - compiler: ghc-9.8.2
41+ compilerKind: ghc
42+ compilerVersion: 9.8.2
43+ setup-method: ghcup
44+ allow-failure: false
45+ - compiler: ghc-9.6.6
46+ compilerKind: ghc
47+ compilerVersion: 9.6.6
48+ setup-method: ghcup
49+ allow-failure: false
50+ - compiler: ghc-9.4.8
51+ compilerKind: ghc
52+ compilerVersion: 9.4.8
53+ setup-method: ghcup
54+ allow-failure: false
55+ - compiler: ghc-9.2.8
56+ compilerKind: ghc
57+ compilerVersion: 9.2.8
58+ setup-method: ghcup
59+ allow-failure: false
60+ - compiler: ghc-9.0.2
61+ compilerKind: ghc
62+ compilerVersion: 9.0.2
63+ setup-method: ghcup
64+ allow-failure: false
65+ - compiler: ghc-8.10.7
66+ compilerKind: ghc
67+ compilerVersion: 8.10.7
68+ setup-method: ghcup
69+ allow-failure: false
70+ - compiler: ghc-8.8.4
71+ compilerKind: ghc
72+ compilerVersion: 8.8.4
73+ setup-method: ghcup
74+ allow-failure: false
75+ - compiler: ghc-8.6.5
76+ compilerKind: ghc
77+ compilerVersion: 8.6.5
78+ setup-method: ghcup
79+ allow-failure: false
80+ fail-fast: false
81+ steps:
82+ - name: apt
83+ run: |
84+ apt-get update
85+ apt-get install -y --no-install-recommends gnupg ca-certificates dirmngr curl git software-properties-common libtinfo5
86+ mkdir -p "$HOME/.ghcup/bin"
87+ curl -sL https://downloads.haskell.org/ghcup/0.1.20.0/x86_64-linux-ghcup-0.1.20.0 > "$HOME/.ghcup/bin/ghcup"
88+ chmod a+x "$HOME/.ghcup/bin/ghcup"
89+ "$HOME/.ghcup/bin/ghcup" install ghc "$HCVER" || (cat "$HOME"/.ghcup/logs/*.* && false)
90+ "$HOME/.ghcup/bin/ghcup" install cabal 3.12.1.0 || (cat "$HOME"/.ghcup/logs/*.* && false)
91+ env:
92+ HCKIND: ${{ matrix.compilerKind }}
93+ HCNAME: ${{ matrix.compiler }}
94+ HCVER: ${{ matrix.compilerVersion }}
95+ - name: Set PATH and environment variables
96+ run: |
97+ echo "$HOME/.cabal/bin" >> $GITHUB_PATH
98+ echo "LANG=C.UTF-8" >> "$GITHUB_ENV"
99+ echo "CABAL_DIR=$HOME/.cabal" >> "$GITHUB_ENV"
100+ echo "CABAL_CONFIG=$HOME/.cabal/config" >> "$GITHUB_ENV"
101+ HCDIR=/opt/$HCKIND/$HCVER
102+ HC=$("$HOME/.ghcup/bin/ghcup" whereis ghc "$HCVER")
103+ HCPKG=$(echo "$HC" | sed 's#ghc$#ghc-pkg#')
104+ HADDOCK=$(echo "$HC" | sed 's#ghc$#haddock#')
105+ echo "HC=$HC" >> "$GITHUB_ENV"
106+ echo "HCPKG=$HCPKG" >> "$GITHUB_ENV"
107+ echo "HADDOCK=$HADDOCK" >> "$GITHUB_ENV"
108+ echo "CABAL=$HOME/.ghcup/bin/cabal-3.12.1.0 -vnormal+nowrap" >> "$GITHUB_ENV"
109+ HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\d+)\.(\d+)\.(\d+)(\.(\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')
110+ echo "HCNUMVER=$HCNUMVER" >> "$GITHUB_ENV"
111+ echo "ARG_TESTS=--enable-tests" >> "$GITHUB_ENV"
112+ echo "ARG_BENCH=--enable-benchmarks" >> "$GITHUB_ENV"
113+ echo "HEADHACKAGE=false" >> "$GITHUB_ENV"
114+ echo "ARG_COMPILER=--$HCKIND --with-compiler=$HC" >> "$GITHUB_ENV"
115+ echo "GHCJSARITH=0" >> "$GITHUB_ENV"
116+ env:
117+ HCKIND: ${{ matrix.compilerKind }}
118+ HCNAME: ${{ matrix.compiler }}
119+ HCVER: ${{ matrix.compilerVersion }}
120+ - name: env
121+ run: |
122+ env
123+ - name: write cabal config
124+ run: |
125+ mkdir -p $CABAL_DIR
126+ cat >> $CABAL_CONFIG <<EOF
127+ remote-build-reporting: anonymous
128+ write-ghc-environment-files: never
129+ remote-repo-cache: $CABAL_DIR/packages
130+ logs-dir: $CABAL_DIR/logs
131+ world-file: $CABAL_DIR/world
132+ extra-prog-path: $CABAL_DIR/bin
133+ symlink-bindir: $CABAL_DIR/bin
134+ installdir: $CABAL_DIR/bin
135+ build-summary: $CABAL_DIR/logs/build.log
136+ store-dir: $CABAL_DIR/store
137+ install-dirs user
138+ prefix: $CABAL_DIR
139+ repository hackage.haskell.org
140+ url: http://hackage.haskell.org/
141+ EOF
142+ cat >> $CABAL_CONFIG <<EOF
143+ program-default-options
144+ ghc-options: $GHCJOBS +RTS -M3G -RTS
145+ EOF
146+ cat $CABAL_CONFIG
147+ - name: versions
148+ run: |
149+ $HC --version || true
150+ $HC --print-project-git-commit-id || true
151+ $CABAL --version || true
152+ - name: update cabal index
153+ run: |
154+ $CABAL v2-update -v
155+ - name: install cabal-plan
156+ run: |
157+ mkdir -p $HOME/.cabal/bin
158+ curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.7.3.0/cabal-plan-0.7.3.0-x86_64-linux.xz > cabal-plan.xz
159+ echo 'f62ccb2971567a5f638f2005ad3173dba14693a45154c1508645c52289714cb2 cabal-plan.xz' | sha256sum -c -
160+ xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan
161+ rm -f cabal-plan.xz
162+ chmod a+x $HOME/.cabal/bin/cabal-plan
163+ cabal-plan --version
164+ - name: checkout
165+ uses: actions/checkout@v4
166+ with:
167+ path: source
168+ - name: initial cabal.project for sdist
169+ run: |
170+ touch cabal.project
171+ echo "packages: $GITHUB_WORKSPACE/source/uuid-bench" >> cabal.project
172+ cat cabal.project
173+ - name: sdist
174+ run: |
175+ mkdir -p sdist
176+ $CABAL sdist all --output-dir $GITHUB_WORKSPACE/sdist
177+ - name: unpack
178+ run: |
179+ mkdir -p unpacked
180+ find sdist -maxdepth 1 -type f -name '*.tar.gz' -exec tar -C $GITHUB_WORKSPACE/unpacked -xzvf {} \;
181+ - name: generate cabal.project
182+ run: |
183+ PKGDIR_uuid_bench="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/uuid-bench-[0-9.]*')"
184+ echo "PKGDIR_uuid_bench=${PKGDIR_uuid_bench}" >> "$GITHUB_ENV"
185+ rm -f cabal.project cabal.project.local
186+ touch cabal.project
187+ touch cabal.project.local
188+ echo "packages: ${PKGDIR_uuid_bench}" >> cabal.project
189+ echo "package uuid-bench" >> cabal.project
190+ echo " ghc-options: -Werror=missing-methods" >> cabal.project
191+ cat >> cabal.project <<EOF
192+ EOF
193+ $HCPKG list --simple-output --names-only | perl -ne 'for (split /\s+/) { print "constraints: any.$_ installed\n" unless /^(uuid-bench)$/; }' >> cabal.project.local
194+ cat cabal.project
195+ cat cabal.project.local
196+ - name: dump install plan
197+ run: |
198+ $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dry-run all
199+ cabal-plan
200+ - name: restore cache
201+ uses: actions/cache/restore@v4
202+ with:
203+ key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }}
204+ path: ~/.cabal/store
205+ restore-keys: ${{ runner.os }}-${{ matrix.compiler }}-
206+ - name: install dependencies
207+ run: |
208+ $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --dependencies-only -j2 all
209+ $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dependencies-only -j2 all
210+ - name: build w/o tests
211+ run: |
212+ $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all
213+ - name: build
214+ run: |
215+ $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --write-ghc-environment-files=always
216+ - name: cabal check
217+ run: |
218+ cd ${PKGDIR_uuid_bench} || false
219+ ${CABAL} -vnormal check
220+ - name: haddock
221+ run: |
222+ $CABAL v2-haddock --disable-documentation --haddock-all $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH all
223+ - name: unconstrained build
224+ run: |
225+ rm -f cabal.project.local
226+ $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all
227+ - name: prepare for constraint sets
228+ run: |
229+ rm -f cabal.project.local
230+ - name: constraint set random-1.2
231+ run: |
232+ $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='random==1.2.*' all --dry-run
233+ cabal-plan topo | sort
234+ $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='random==1.2.*' --dependencies-only -j2 all
235+ $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='random==1.2.*' all
236+ - name: save cache
237+ uses: actions/cache/save@v4
238+ if: always()
239+ with:
240+ key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }}
241+ path: ~/.cabal/store
.github/workflows/haskell-ci.ymlnew file+262
@@ -0,0 +1,262 @@
1+# This GitHub workflow config has been generated by a script via
2+#
3+# haskell-ci 'github' 'cabal.project'
4+#
5+# To regenerate the script (for example after adjusting tested-with) run
6+#
7+# haskell-ci regenerate
8+#
9+# For more information, see https://github.com/haskell-CI/haskell-ci
10+#
11+# version: 0.19.20241223
12+#
13+# REGENDATA ("0.19.20241223",["github","cabal.project"])
14+#
15+name: Haskell-CI
16+on:
17+ push:
18+ branches:
19+ - master
20+ pull_request:
21+ branches:
22+ - master
23+jobs:
24+ linux:
25+ name: Haskell-CI - Linux - ${{ matrix.compiler }}
26+ runs-on: ubuntu-20.04
27+ timeout-minutes:
28+ 60
29+ container:
30+ image: buildpack-deps:jammy
31+ continue-on-error: ${{ matrix.allow-failure }}
32+ strategy:
33+ matrix:
34+ include:
35+ - compiler: ghc-9.12.1
36+ compilerKind: ghc
37+ compilerVersion: 9.12.1
38+ setup-method: ghcup
39+ allow-failure: false
40+ - compiler: ghc-9.10.1
41+ compilerKind: ghc
42+ compilerVersion: 9.10.1
43+ setup-method: ghcup
44+ allow-failure: false
45+ - compiler: ghc-9.8.4
46+ compilerKind: ghc
47+ compilerVersion: 9.8.4
48+ setup-method: ghcup
49+ allow-failure: false
50+ - compiler: ghc-9.6.6
51+ compilerKind: ghc
52+ compilerVersion: 9.6.6
53+ setup-method: ghcup
54+ allow-failure: false
55+ - compiler: ghc-9.4.8
56+ compilerKind: ghc
57+ compilerVersion: 9.4.8
58+ setup-method: ghcup
59+ allow-failure: false
60+ - compiler: ghc-9.2.8
61+ compilerKind: ghc
62+ compilerVersion: 9.2.8
63+ setup-method: ghcup
64+ allow-failure: false
65+ - compiler: ghc-9.0.2
66+ compilerKind: ghc
67+ compilerVersion: 9.0.2
68+ setup-method: ghcup
69+ allow-failure: false
70+ - compiler: ghc-8.10.7
71+ compilerKind: ghc
72+ compilerVersion: 8.10.7
73+ setup-method: ghcup
74+ allow-failure: false
75+ - compiler: ghc-8.8.4
76+ compilerKind: ghc
77+ compilerVersion: 8.8.4
78+ setup-method: ghcup
79+ allow-failure: false
80+ - compiler: ghc-8.6.5
81+ compilerKind: ghc
82+ compilerVersion: 8.6.5
83+ setup-method: ghcup
84+ allow-failure: false
85+ fail-fast: false
86+ steps:
87+ - name: apt-get install
88+ run: |
89+ apt-get update
90+ apt-get install -y --no-install-recommends gnupg ca-certificates dirmngr curl git software-properties-common libtinfo5
91+ - name: Install GHCup
92+ run: |
93+ mkdir -p "$HOME/.ghcup/bin"
94+ curl -sL https://downloads.haskell.org/ghcup/0.1.30.0/x86_64-linux-ghcup-0.1.30.0 > "$HOME/.ghcup/bin/ghcup"
95+ chmod a+x "$HOME/.ghcup/bin/ghcup"
96+ - name: Install cabal-install
97+ run: |
98+ "$HOME/.ghcup/bin/ghcup" install cabal 3.14.1.0 || (cat "$HOME"/.ghcup/logs/*.* && false)
99+ echo "CABAL=$HOME/.ghcup/bin/cabal-3.14.1.0 -vnormal+nowrap" >> "$GITHUB_ENV"
100+ - name: Install GHC (GHCup)
101+ if: matrix.setup-method == 'ghcup'
102+ run: |
103+ "$HOME/.ghcup/bin/ghcup" install ghc "$HCVER" || (cat "$HOME"/.ghcup/logs/*.* && false)
104+ HC=$("$HOME/.ghcup/bin/ghcup" whereis ghc "$HCVER")
105+ HCPKG=$(echo "$HC" | sed 's#ghc$#ghc-pkg#')
106+ HADDOCK=$(echo "$HC" | sed 's#ghc$#haddock#')
107+ echo "HC=$HC" >> "$GITHUB_ENV"
108+ echo "HCPKG=$HCPKG" >> "$GITHUB_ENV"
109+ echo "HADDOCK=$HADDOCK" >> "$GITHUB_ENV"
110+ env:
111+ HCKIND: ${{ matrix.compilerKind }}
112+ HCNAME: ${{ matrix.compiler }}
113+ HCVER: ${{ matrix.compilerVersion }}
114+ - name: Set PATH and environment variables
115+ run: |
116+ echo "$HOME/.cabal/bin" >> $GITHUB_PATH
117+ echo "LANG=C.UTF-8" >> "$GITHUB_ENV"
118+ echo "CABAL_DIR=$HOME/.cabal" >> "$GITHUB_ENV"
119+ echo "CABAL_CONFIG=$HOME/.cabal/config" >> "$GITHUB_ENV"
120+ HCNUMVER=$(${HC} --numeric-version|perl -ne '/^(\d+)\.(\d+)\.(\d+)(\.(\d+))?$/; print(10000 * $1 + 100 * $2 + ($3 == 0 ? $5 != 1 : $3))')
121+ echo "HCNUMVER=$HCNUMVER" >> "$GITHUB_ENV"
122+ echo "ARG_TESTS=--enable-tests" >> "$GITHUB_ENV"
123+ echo "ARG_BENCH=--enable-benchmarks" >> "$GITHUB_ENV"
124+ echo "HEADHACKAGE=false" >> "$GITHUB_ENV"
125+ echo "ARG_COMPILER=--$HCKIND --with-compiler=$HC" >> "$GITHUB_ENV"
126+ env:
127+ HCKIND: ${{ matrix.compilerKind }}
128+ HCNAME: ${{ matrix.compiler }}
129+ HCVER: ${{ matrix.compilerVersion }}
130+ - name: env
131+ run: |
132+ env
133+ - name: write cabal config
134+ run: |
135+ mkdir -p $CABAL_DIR
136+ cat >> $CABAL_CONFIG <<EOF
137+ remote-build-reporting: anonymous
138+ write-ghc-environment-files: never
139+ remote-repo-cache: $CABAL_DIR/packages
140+ logs-dir: $CABAL_DIR/logs
141+ world-file: $CABAL_DIR/world
142+ extra-prog-path: $CABAL_DIR/bin
143+ symlink-bindir: $CABAL_DIR/bin
144+ installdir: $CABAL_DIR/bin
145+ build-summary: $CABAL_DIR/logs/build.log
146+ store-dir: $CABAL_DIR/store
147+ install-dirs user
148+ prefix: $CABAL_DIR
149+ repository hackage.haskell.org
150+ url: http://hackage.haskell.org/
151+ EOF
152+ cat >> $CABAL_CONFIG <<EOF
153+ program-default-options
154+ ghc-options: $GHCJOBS +RTS -M3G -RTS
155+ EOF
156+ cat $CABAL_CONFIG
157+ - name: versions
158+ run: |
159+ $HC --version || true
160+ $HC --print-project-git-commit-id || true
161+ $CABAL --version || true
162+ - name: update cabal index
163+ run: |
164+ $CABAL v2-update -v
165+ - name: install cabal-plan
166+ run: |
167+ mkdir -p $HOME/.cabal/bin
168+ curl -sL https://github.com/haskell-hvr/cabal-plan/releases/download/v0.7.3.0/cabal-plan-0.7.3.0-x86_64-linux.xz > cabal-plan.xz
169+ echo 'f62ccb2971567a5f638f2005ad3173dba14693a45154c1508645c52289714cb2 cabal-plan.xz' | sha256sum -c -
170+ xz -d < cabal-plan.xz > $HOME/.cabal/bin/cabal-plan
171+ rm -f cabal-plan.xz
172+ chmod a+x $HOME/.cabal/bin/cabal-plan
173+ cabal-plan --version
174+ - name: checkout
175+ uses: actions/checkout@v4
176+ with:
177+ path: source
178+ - name: initial cabal.project for sdist
179+ run: |
180+ touch cabal.project
181+ echo "packages: $GITHUB_WORKSPACE/source/uuid-types" >> cabal.project
182+ echo "packages: $GITHUB_WORKSPACE/source/uuid" >> cabal.project
183+ cat cabal.project
184+ - name: sdist
185+ run: |
186+ mkdir -p sdist
187+ $CABAL sdist all --output-dir $GITHUB_WORKSPACE/sdist
188+ - name: unpack
189+ run: |
190+ mkdir -p unpacked
191+ find sdist -maxdepth 1 -type f -name '*.tar.gz' -exec tar -C $GITHUB_WORKSPACE/unpacked -xzvf {} \;
192+ - name: generate cabal.project
193+ run: |
194+ PKGDIR_uuid_types="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/uuid-types-[0-9.]*')"
195+ echo "PKGDIR_uuid_types=${PKGDIR_uuid_types}" >> "$GITHUB_ENV"
196+ PKGDIR_uuid="$(find "$GITHUB_WORKSPACE/unpacked" -maxdepth 1 -type d -regex '.*/uuid-[0-9.]*')"
197+ echo "PKGDIR_uuid=${PKGDIR_uuid}" >> "$GITHUB_ENV"
198+ rm -f cabal.project cabal.project.local
199+ touch cabal.project
200+ touch cabal.project.local
201+ echo "packages: ${PKGDIR_uuid_types}" >> cabal.project
202+ echo "packages: ${PKGDIR_uuid}" >> cabal.project
203+ echo "package uuid-types" >> cabal.project
204+ echo " ghc-options: -Werror=missing-methods" >> cabal.project
205+ echo "package uuid" >> cabal.project
206+ echo " ghc-options: -Werror=missing-methods" >> cabal.project
207+ cat >> cabal.project <<EOF
208+ EOF
209+ $HCPKG list --simple-output --names-only | perl -ne 'for (split /\s+/) { print "constraints: any.$_ installed\n" unless /^(uuid|uuid-types)$/; }' >> cabal.project.local
210+ cat cabal.project
211+ cat cabal.project.local
212+ - name: dump install plan
213+ run: |
214+ $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dry-run all
215+ cabal-plan
216+ - name: restore cache
217+ uses: actions/cache/restore@v4
218+ with:
219+ key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }}
220+ path: ~/.cabal/store
221+ restore-keys: ${{ runner.os }}-${{ matrix.compiler }}-
222+ - name: install dependencies
223+ run: |
224+ $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --dependencies-only -j2 all
225+ $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH --dependencies-only -j2 all
226+ - name: build w/o tests
227+ run: |
228+ $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all
229+ - name: build
230+ run: |
231+ $CABAL v2-build $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --write-ghc-environment-files=always
232+ - name: tests
233+ run: |
234+ $CABAL v2-test $ARG_COMPILER $ARG_TESTS $ARG_BENCH all --test-show-details=direct
235+ - name: cabal check
236+ run: |
237+ cd ${PKGDIR_uuid_types} || false
238+ ${CABAL} -vnormal check
239+ cd ${PKGDIR_uuid} || false
240+ ${CABAL} -vnormal check
241+ - name: haddock
242+ run: |
243+ $CABAL v2-haddock --disable-documentation --haddock-all $ARG_COMPILER --with-haddock $HADDOCK $ARG_TESTS $ARG_BENCH all
244+ - name: unconstrained build
245+ run: |
246+ rm -f cabal.project.local
247+ $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks all
248+ - name: prepare for constraint sets
249+ run: |
250+ rm -f cabal.project.local
251+ - name: constraint set random-1.2
252+ run: |
253+ $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='random==1.2.*' all --dry-run
254+ cabal-plan topo | sort
255+ $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='random==1.2.*' --dependencies-only -j2 all
256+ $CABAL v2-build $ARG_COMPILER --disable-tests --disable-benchmarks --constraint='random==1.2.*' all
257+ - name: save cache
258+ if: always()
259+ uses: actions/cache/save@v4
260+ with:
261+ key: ${{ runner.os }}-${{ matrix.compiler }}-${{ github.sha }}
262+ path: ~/.cabal/store
.gitignore+5−1
@@ -1,4 +1,3 @@
1−
2# Sandboxing
1# Sandboxing
3.cabal-sandbox/
2.cabal-sandbox/
4cabal.sandbox.config
3cabal.sandbox.config
@@ -6,4 +5,9 @@ cabal.sandbox.config
6# Cabal stuff
5# Cabal stuff
7dist/
6dist/
8cabal.config
7cabal.config
8+dist-newstyle/
9+/cabal.project.local
10+.ghc.environment.*
9
11
12+# Emacs
13+*~
.travis.ymldeleted−11
@@ -1,11 +0,0 @@
1−language: haskell
2−ghc:
3− - 7.8
4− - 7.6
5− - 7.4
6−
7−sudo: false
8−install:
9− - ./travis-scripts/install.sh
10−script:
11− - ./travis-scripts/build.sh
uuid-types/CONTRIBUTORS → CONTRIBUTORSrenamed+2
@@ -11,3 +11,5 @@ davean
11Francesco Mazzoli
11Francesco Mazzoli
12Michael Snoyman
12Michael Snoyman
13Bardur Arantsson
13Bardur Arantsson
14+Timo von Holtz
15+Oleg Grenrus
Policy.mdnew file+11
@@ -0,0 +1,11 @@
1+# Versioning
2+
3+Because many consumers of the `UUID` type receive the type
4+through the `uuid` package and not the `uuid-types` package
5+we need to be careful about removing instances from the `uuid`
6+type.
7+
8+If the `uuid-types` package has a major-version bump because of
9+the removal of a class instance then we must also bump the major
10+version of the `uuid` package when we update the package
11+description to pull in the new version of `uuid-types`.
README.md+9−1
@@ -1,4 +1,12 @@
1−# uuid [![Build Status](https://travis-ci.org/aslatter/uuid.svg?branch=master)](https://travis-ci.org/aslatter/uuid)
1+# uuid [![Build Status](https://travis-ci.org/hvr/uuid.svg?branch=master)](https://travis-ci.org/hvr/uuid)
2
2
3This library is useful for creating, comparing, parsing and printing Universally
3This library is useful for creating, comparing, parsing and printing Universally
4Unique Identifiers. See http://en.wikipedia.org/wiki/UUID for the general idea.
4Unique Identifiers. See http://en.wikipedia.org/wiki/UUID for the general idea.
5+
6+We offer two different packages: `uuid` and `uuid-types`
7+
8+The `uuid` package aims to be a fully-featured library for working with UUIDs.
9+
10+However if you're developing a library and only want the `UUID` type to show up
11+in your APIs you may want to use the `uuid-types` library to minimize the number
12+of dependencies needed by users of your library.
cabal.bench.projectnew file+4
@@ -0,0 +1,4 @@
1+-- separate package for benchmarks
2+-- this way we can build criterion
3+packages: uuid-bench
4+benchmarks: True
cabal.haskell-cinew file+7
@@ -0,0 +1,7 @@
1+branches: master
2+-- jobs-selection: any
3+head-hackage: False
4+
5+constraint-set random-1.2
6+ ghc: >=7.10
7+ constraints: random==1.2.*
cabal.projectnew file+15
@@ -0,0 +1,15 @@
1+-- see http://cabal.readthedocs.io/en/latest/nix-local-build.html
2+-- for more details
3+
4+packages: uuid-types/
5+packages: uuid/
6+
7+package uuid-types
8+ tests: True
9+ -- profiling: True
10+ -- profiling-detail: toplevel-functions
11+
12+package uuid
13+ tests: True
14+ -- profiling: True
15+ -- profiling-detail: toplevel-functions
gen-ci.shnew file+5
@@ -0,0 +1,5 @@
1+#!/bin/sh
2+
3+# haskell-ci doesn't know how to regenerate multiple GHA workflows
4+haskell-ci github cabal.project
5+haskell-ci github --project cabal.bench.project -o .github/workflows/haskell-ci-bench.yml --github-action-name Benchmarks
travis-scripts/build.shdeleted−27
@@ -1,27 +0,0 @@
1−#!/usr/bin/env sh
2−echo "==========================================="
3−echo "= Building and installing 'uuid-types'... ="
4−echo "==========================================="
5−
6−# We install here because "uuid" is going to need it.
7−(cd "uuid-types" && \
8− cabal configure --enable-tests && \
9− cabal build && \
10− cabal test && \
11− cabal install) || exit 1
12−
13−echo "========================================="
14−echo "= Installing dependencies for 'uuid'... ="
15−echo "========================================="
16−
17−(cd "uuid" && \
18− cabal install --dependencies-only --enable-tests) || exit 1
19−
20−echo "======================"
21−echo "= Building 'uuid'... ="
22−echo "======================"
23−
24−(cd "uuid" && \
25− cabal configure --enable-tests && \
26− cabal build && \
27− cabal test) || exit 1
travis-scripts/install.shdeleted−13
@@ -1,13 +0,0 @@
1−#!/usr/bin/env sh
2−
3−# We can only pre-install dependencies for the "uuid-types" project
4−# since the "uuid" project depends on "uuid-types". We could use
5−# sandboxing and "add-source", but it seems quite wasteful of
6−# CPU-cycles to compile everything twice for each version of GHC.
7−
8−echo "==============================================="
9−echo "= Installing dependencies for 'uuid-types'... ="
10−echo "==============================================="
11−
12−(cd "uuid-types" && \
13− cabal install --dependencies-only --enable-tests) || exit 1
uuid-bench/LICENSEnew file+28
@@ -0,0 +1,28 @@
1+Copyright (c) 2008, Antoine Latter
2+
3+All rights reserved.
4+
5+Redistribution and use in source and binary forms, with or without
6+modification, are permitted provided that the following conditions are
7+met:
8+
9+ * Redistributions of source code must retain the above copyright
10+notice, this list of conditions and the following disclaimer.
11+ * Redistributions in binary form must reproduce the above copyright
12+notice, this list of conditions and the following disclaimer in the
13+documentation and/or other materials provided with the distribution.
14+ * The names of the authors may not be used to endorse or promote
15+products derived from this software without specific prior written
16+permission.
17+
18+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
24+TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
uuid/tests/BenchUUID.hs → uuid-bench/bench/uuid-benchmark.hsrenamed+3−4
@@ -1,11 +1,9 @@
1−{-# LANGUAGE CPP #-}
2−
3import Criterion.Main
1import Criterion.Main
4import Data.Char (ord)
2import Data.Char (ord)
5import Data.IORef
3import Data.IORef
6import Data.Word
4import Data.Word
7import qualified Data.UUID as U
5import qualified Data.UUID as U
8−import qualified Data.UUID.V1 as U
6+import qualified Data.UUID.V4 as U
9import qualified Data.UUID.V3 as U3
7import qualified Data.UUID.V3 as U3
10import qualified Data.UUID.V5 as U5
8import qualified Data.UUID.V5 as U5
11import System.Random
9import System.Random
@@ -27,7 +25,8 @@ main = do
27 defaultMain [
25 defaultMain [
28 bgroup "generation" [
26 bgroup "generation" [
29 bench "V1" $ nfIO U.nextUUID,
27 bench "V1" $ nfIO U.nextUUID,
28+ bench "V4-stock" $ nfIO (U.nextRandom :: IO U.UUID),
30− bench "V4" $ nfIO (randomUUID :: IO U.UUID),
29+ bench "V4-mersenne" $ nfIO (randomUUID :: IO U.UUID),
31 bench "V3" $ nf (U3.generateNamed U3.namespaceURL) n1,
30 bench "V3" $ nf (U3.generateNamed U3.namespaceURL) n1,
32 bench "V5" $ nf (U5.generateNamed U5.namespaceURL) n1
31 bench "V5" $ nf (U5.generateNamed U5.namespaceURL) n1
33 ]
32 ]
uuid-types/tests/BenchUUID.hs → uuid-bench/bench/uuid-types-benchmark.hsrenamed+56−40
@@ -1,19 +1,22 @@
1{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
2
2
3#if !(MIN_VERSION_bytestring(0,10,0))
3#if !(MIN_VERSION_bytestring(0,10,0))
4+{-# OPTIONS_GHC -fno-warn-orphans #-}
4-- Needed for NFData instance
5-- Needed for NFData instance
5−import Control.DeepSeq
6+import Control.DeepSeq
6import qualified Data.ByteString.Lazy.Internal as BL
7import qualified Data.ByteString.Lazy.Internal as BL
7#endif
8#endif
8−import Criterion.Main
9+import Criterion.Main
9−import Data.Maybe (fromJust)
10−import qualified Data.Set as Set
11−import qualified Data.ByteString.Lazy as BL
10+import qualified Data.ByteString.Lazy as BL
12−import qualified Data.UUID.Types as U
11+import qualified Data.HashSet as HashSet
12+import Data.Maybe (fromJust)
13+import qualified Data.Set as Set
14+import qualified Data.UUID.Types as U
13−import Foreign (alloca, peek, poke)
15+import Foreign (alloca, peek, poke)
14−import System.Random
16+import System.Random
15
17
16#if !(MIN_VERSION_bytestring(0,10,0))
18#if !(MIN_VERSION_bytestring(0,10,0))
19+-- orphan
17instance NFData BL.ByteString where
20instance NFData BL.ByteString where
18 rnf BL.Empty = ()
21 rnf BL.Empty = ()
19 rnf (BL.Chunk _ ts) = rnf ts
22 rnf (BL.Chunk _ ts) = rnf ts
@@ -21,43 +24,56 @@ instance NFData BL.ByteString where
21
24
22main :: IO ()
25main :: IO ()
23main = do
26main = do
24− u1 <- randomIO
27+ u1 <- randomIO
25− let s1 = U.toString u1
28+ let s1 = U.toString u1
26− b1 = U.toByteString u1
29+ b1 = U.toByteString u1
30+ a1 = U.toASCIIBytes u1
31+ t1 = U.toText u1
32+ (w1a,w1b,w1c,w1d) = U.toWords u1
27− nil2 = fromJust $
33+ nil2 = fromJust $
28− U.fromString "00000000-0000-0000-0000-000000000000"
34+ U.fromString "00000000-0000-0000-0000-000000000000"
29− u2a = fromJust $ U.fromString "169a5a43-c051-4a16-98f4-08447ddd5dc0"
35+ u2a = fromJust $ U.fromString "169a5a43-c051-4a16-98f4-08447ddd5dc0"
30− u2b = fromJust $ U.fromByteString $
36+ u2b = fromJust $ U.fromByteString $
31− BL.pack [0x16, 0x9a, 0x5a, 0x43, 0xc0, 0x51, 0x4a, 0x16,
37+ BL.pack [0x16, 0x9a, 0x5a, 0x43, 0xc0, 0x51, 0x4a, 0x16,
32− 0x98, 0xf4, 0x08, 0x44, 0x7d, 0xdd, 0x5d, 0xc0]
38+ 0x98, 0xf4, 0x08, 0x44, 0x7d, 0xdd, 0x5d, 0xc0]
33− u3 = fromJust $ U.fromString "dea6f619-1038-438b-b4af-f1cdec1e6e23"
39+ u3 = fromJust $ U.fromString "dea6f619-1038-438b-b4af-f1cdec1e6e23"
34
40
35− -- setup for Storable benchmark
41+ -- setup for Storable benchmark
36− alloca $ \ uuidPtr -> do
42+ alloca $ \ uuidPtr -> do
37
43
38− poke uuidPtr u1
44+ poke uuidPtr u1
39
45
40− defaultMain [
46+ defaultMain [
41− bgroup "testing" [
47+ bgroup "testing" [
42− bench "null non-nil" $ whnf U.null u1,
48+ bench "null non-nil" $ whnf U.null u1,
43− bench "null nil" $ whnf U.null U.nil,
49+ bench "null nil" $ whnf U.null U.nil,
44− bench "null nil2" $ whnf U.null nil2,
50+ bench "null nil2" $ whnf U.null nil2,
45− bench "eq same" $ whnf (==u2a) u2b,
51+ bench "eq same" $ whnf (==u2a) u2b,
46− bench "eq differ" $ whnf (==u2a) u3
52+ bench "eq differ" $ whnf (==u2a) u3,
53+ bench "compare same" $ whnf (compare u2a) u2b,
54+ bench "compare differ" $ whnf (compare u2a) u3
47− ],
55+ ],
48− bgroup "conversion" [
56+ bgroup "conversion" [
49− bench "toString" $ nf U.toString u1,
57+ bench "toString" $ nf U.toString u1,
50− bench "fromString" $ nf U.fromString s1,
58+ bench "fromString" $ nf U.fromString s1,
51− bench "toByteString" $ nf U.toByteString u1,
59+ bench "toByteString" $ nf U.toByteString u1,
52− bench "fromByteString" $ nf U.fromByteString b1
60+ bench "fromByteString" $ nf U.fromByteString b1,
53− ],
61+ bench "toASCIIBytes" $ nf U.toASCIIBytes u1,
54− bench "set making" $ nf Set.fromList uuids,
62+ bench "fromASCIIBytes" $ nf U.fromASCIIBytes a1,
63+ bench "toWords" $ nf U.toWords u1,
64+ bench "fromWords" $ nf (U.fromWords w1a w1b w1c) w1d,
65+ bench "toText" $ nf U.toText u1,
66+ bench "fromText" $ nf U.fromText t1
67+ ],
55
68
69+ bench "Set making" $ nf Set.fromList uuids,
70+ bench "HashSet making" $ nf HashSet.fromList uuids,
71+
56− bgroup "storable" [
72+ bgroup "storable" [
57− bench "peek" $ nfIO (peek uuidPtr),
73+ bench "peek" $ nfIO (peek uuidPtr),
58− bench "poke" $ poke uuidPtr u1
74+ bench "poke" $ whnfIO $ poke uuidPtr u1
59− ]
60 ]
75 ]
76+ ]
61
77
62-- 50 uuids, so tests can be repeatable
78-- 50 uuids, so tests can be repeatable
63uuids :: [U.UUID]
79uuids :: [U.UUID]
uuid-bench/src-uuidnew file+1
@@ -0,0 +1 @@
1+../uuid/src
uuid-bench/src-uuid-typesnew file+1
@@ -0,0 +1 @@
1+../uuid-types/src
uuid-bench/uuid-bench.cabalnew file+126
@@ -0,0 +1,126 @@
1+cabal-version: 1.12
2+name: uuid-bench
3+version: 0
4+copyright:
5+ (c) 2017-2018 Herbert Valerio Riedel
6+ (c) 2008-2014 Antoine Latter
7+
8+author: Antoine Latter
9+maintainer: Oleg Grenrus <oleg.grenrus@iki.fi>
10+license: BSD3
11+license-file: LICENSE
12+category: Data
13+build-type: Simple
14+
15+-- Benchmarking with older GHCs is not meaningful
16+tested-with:
17+ GHC ==8.6.5
18+ || ==8.8.4
19+ || ==8.10.7
20+ || ==9.0.2
21+ || ==9.2.8
22+ || ==9.4.8
23+ || ==9.6.6
24+ || ==9.8.2
25+ || ==9.10.1
26+
27+synopsis: UUID benchmarks
28+description:
29+ UUID benchmarks.
30+ This package is combined uuid and uuid-types, renamed so we do not
31+ cause benchmark tools to be build against local package.
32+
33+homepage: https://github.com/haskell-hvr/uuid
34+bug-reports: https://github.com/haskell-hvr/uuid/issues
35+
36+source-repository head
37+ type: git
38+ location: https://github.com/haskell-hvr/uuid.git
39+ subdir: uuid-bench
40+
41+library
42+ build-depends:
43+ base >=4.12.0.0 && <5
44+ , binary >=0.8.6.0 && <0.9
45+ , bytestring >=0.10.8.2 && <0.13
46+ , cryptohash-md5 >=0.11.100 && <0.12
47+ , cryptohash-sha1 >=0.11.100 && <0.12
48+ , deepseq >=1.4.4.0 && <1.6
49+ , entropy >=0.3.7 && <0.5
50+ , hashable >=1.4.4.0 && <1.6
51+ , network-info >=0.2 && <0.3
52+ , random >=1.2.1.2 && <1.3
53+ , template-haskell >=2.14.0.0 && <2.23
54+ , text >=1.2.3.0 && <1.3 || >=2.0 && <2.2
55+ , time >=1.4 && <1.13
56+
57+ -- uuid modules
58+ exposed-modules:
59+ Data.UUID
60+ Data.UUID.Util
61+ Data.UUID.V3
62+ Data.UUID.V4
63+ Data.UUID.V5
64+
65+ other-modules:
66+ Data.UUID.Named
67+ Data.Word.Util
68+
69+ -- uuid-types modules
70+ exposed-modules: Data.UUID.Types
71+
72+ -- Exposed for companion projects; *NOT* part of the official API:
73+ exposed-modules:
74+ Data.UUID.Types.Internal
75+ Data.UUID.Types.Internal.Builder
76+
77+ default-language: Haskell2010
78+ other-extensions:
79+ DeriveDataTypeable
80+ TypeFamilies
81+
82+ ghc-options: -Wall
83+ hs-source-dirs: src-uuid-types src-uuid
84+
85+benchmark uuid-types-benchmark
86+ type: exitcode-stdio-1.0
87+ main-is: uuid-types-benchmark.hs
88+ hs-source-dirs: bench
89+ default-language: Haskell2010
90+ other-extensions: CPP
91+ ghc-options: -Wall
92+
93+ -- inherited constraints
94+ build-depends:
95+ base
96+ , bytestring
97+ , random
98+ , uuid-bench
99+
100+ -- deps w/o inherited constraints
101+ build-depends:
102+ containers >=0.5 && <0.8
103+ , criterion >=1.5 && <1.7
104+ , unordered-containers >=0.2.7 && <0.3
105+
106+benchmark uuid-benchmark
107+ type: exitcode-stdio-1.0
108+ main-is: uuid-benchmark.hs
109+ hs-source-dirs: bench
110+ default-language: Haskell2010
111+ default-extensions:
112+ CPP
113+ DeriveDataTypeable
114+
115+ ghc-options: -Wall -fno-warn-orphans
116+
117+ -- inherited constraints
118+ build-depends:
119+ base
120+ , random
121+ , uuid-bench
122+
123+ -- deps w/o inherited constraints
124+ build-depends:
125+ criterion >=1.5 && <1.7
126+ , mersenne-random-pure64 >=0.2 && <0.3
uuid-types/CHANGESdeleted−3
@@ -1,3 +0,0 @@
1−1.0.0
2−
3−- Initial split from "uuid-1.3.8"
uuid-types/ChangeLog.mdnew file+31
@@ -0,0 +1,31 @@
1+## 1.0.6 (2023-04-16)
2+
3+- Support GHC-8.6.5..GHC-9.10.1
4+
5+## 1.0.5 (2021-05-03)
6+
7+- Add (Template Haskell) `Lift UUID` instance
8+
9+## 1.0.4.0
10+
11+- Declare `Data.UUID.Types` module "`Trustworthy`" with respect to SafeHaskell.
12+- Use more compact heap object representation which saves 16 bytes on 64bit platforms.
13+- Add `toWords64`/`fromWords64` functions
14+- Drop support for GHC < 7.
15+- Add support for `random-1.2`, i.e. idiomatic `Random` and added `Uniform` instances.
16+
17+## 1.0.3
18+
19+- Bump package dependencies.
20+
21+## 1.0.2
22+
23+- Add `toText`/`fromText` functions.
24+
25+## 1.0.1
26+
27+- Update dependencies in tests and benchmarks.
28+
29+## 1.0.0
30+
31+- Initial split from "`uuid-1.3.8`" package.
uuid-types/Data/UUID/Types.hsdeleted−37
@@ -1,37 +0,0 @@
1−{- |
2−Module : Data.UUID.Types
3−Copyright : (c) 2008,2012 Antoine Latter
4−
5−License : BSD-style
6−
7−Maintainer : aslatter@gmail.com
8−Stability : experimental
9−Portability : portable
10−
11−
12−This library is useful for comparing, parsing and
13−printing Universally Unique Identifiers.
14−See <http://en.wikipedia.org/wiki/UUID> for the general idea.
15−See <http://tools.ietf.org/html/rfc4122> for the specification.
16−
17−-}
18−module Data.UUID.Types(UUID
19− ,toString
20− ,fromString
21− ,toASCIIBytes
22− ,fromASCIIBytes
23− ,toLazyASCIIBytes
24− ,fromLazyASCIIBytes
25− ,toByteString
26− ,fromByteString
27− ,toWords
28− ,fromWords
29− ,null
30− ,nil
31− ) where
32−
33−import Prelude () -- we need to hide Prelude.null
34−import Data.UUID.Types.Internal
35−
36−-- Everything is really implemented in Data.UUID.Types.Internal, but I
37−-- don't want to export the constructors out of the package.
uuid-types/cabal.projectnew file+1
@@ -0,0 +1 @@
1+packages: .
uuid-types/src/Data/UUID/Types.hsnew file+47
@@ -0,0 +1,47 @@
1+{-# LANGUAGE Trustworthy #-}
2+
3+{- |
4+Module : Data.UUID.Types
5+Copyright : (c) 2017-2018 Herbert Valerio Riedel
6+ (c) 2008,2012 Antoine Latter
7+
8+License : BSD-style
9+
10+Maintainer : hvr@gnu.org
11+Portability : portable
12+
13+This library is useful for comparing, parsing and
14+printing <http://en.wikipedia.org/wiki/UUID Universally Unique Identifiers (UUID)>.
15+See <http://tools.ietf.org/html/rfc4122 RFC 4122> for the specification.
16+
17+-}
18+module Data.UUID.Types
19+ ( -- * The 'UUID' Type
20+ UUID
21+ -- * Nil UUID
22+ , nil
23+ , null
24+ -- * Textual Representation
25+ , toString
26+ , fromString
27+ , toText
28+ , fromText
29+ , toASCIIBytes
30+ , fromASCIIBytes
31+ , toLazyASCIIBytes
32+ , fromLazyASCIIBytes
33+ -- * Binary Representation
34+ , toByteString
35+ , fromByteString
36+ -- * Integer Representation
37+ , toWords
38+ , fromWords
39+ , toWords64
40+ , fromWords64
41+ ) where
42+
43+import Data.UUID.Types.Internal
44+import Prelude ()
45+
46+-- Everything is really implemented in Data.UUID.Types.Internal, but I
47+-- don't want to export the constructors out of the package.
uuid-types/Data/UUID/Types/Internal.hs → uuid-types/src/Data/UUID/Types/Internal.hsrenamed+205−166
@@ -1,83 +1,86 @@
1+{-# LANGUAGE CPP #-}
1−{-# LANGUAGE DeriveDataTypeable, TypeFamilies, CPP #-}
2+{-# LANGUAGE DeriveDataTypeable #-}
3+{-# LANGUAGE TypeFamilies #-}
4+{-# LANGUAGE ViewPatterns #-}
5+{-# LANGUAGE Unsafe #-}
6+{-# LANGUAGE DeriveLift #-}
7+{-# LANGUAGE StandaloneDeriving #-}
8+{-# OPTIONS_HADDOCK hide #-}
2
9
3-- |
10-- |
4-- Module : Data.UUID.Types.Internal
11-- Module : Data.UUID.Types.Internal
12+-- Copyright : (c) 2017-2018 Herbert Valerio Riedel
5−-- Copyright : (c) 2008-2009, 2012 Antoine Latter
13+-- (c) 2008-2009, 2012 Antoine Latter
6-- (c) 2009 Mark Lentczner
14-- (c) 2009 Mark Lentczner
7--
15--
8-- License : BSD-style
16-- License : BSD-style
9--
17--
10−-- Maintainer : aslatter@gmail.com
18+-- Maintainer : hvr@gnu.org
11−-- Stability : experimental
12-- Portability : portable
19-- Portability : portable
13
20
14module Data.UUID.Types.Internal
21module Data.UUID.Types.Internal
15− (UUID(..)
22+ ( UUID(..)
16− ,null
23+ , null
17− ,nil
24+ , nil
18− ,fromByteString
25+ , fromByteString
19− ,toByteString
26+ , toByteString
20− ,fromString
27+ , fromString
21− ,toString
28+ , toString
29+ , fromText
30+ , toText
22− ,fromWords
31+ , fromWords
23− ,toWords
32+ , toWords
33+ , fromWords64
34+ , toWords64
24− ,toList
35+ , toList
25− ,buildFromBytes
36+ , buildFromBytes
26− ,buildFromWords
37+ , buildFromWords
27− ,fromASCIIBytes
38+ , fromASCIIBytes
28− ,toASCIIBytes
39+ , toASCIIBytes
29− ,fromLazyASCIIBytes
40+ , fromLazyASCIIBytes
30− ,toLazyASCIIBytes
41+ , toLazyASCIIBytes
31− ,UnpackedUUID(..)
42+ , UnpackedUUID(..)
32− ,pack
43+ , pack
33− ,unpack
44+ , unpack
34 ) where
45 ) where
35
46
36−import Prelude hiding (null)
47+import Prelude hiding (null)
37−
48+
38−import Control.Applicative ((<*>))
39−import Control.DeepSeq (NFData(..))
49+import Control.DeepSeq (NFData (..))
40−import Control.Monad (liftM4, guard)
50+import Control.Monad (guard, liftM2)
41−import Data.Functor ((<$>))
51+import Data.Bits
42−import Data.Char
52+import Data.Char
43−import Data.Bits
53+import Data.Data
44−import Data.Hashable
54+import Data.Hashable
45−import Data.List (elemIndices)
55+import Data.List (elemIndices)
46−import Foreign.Ptr (Ptr)
56+import Foreign.Ptr (Ptr)
47−
57+
48−#if MIN_VERSION_base(4,0,0)
49−import Data.Data
50−#else
51−import Data.Generics.Basics
52−#endif
53−
54−import Foreign.Storable
58+import Foreign.Storable
55−
59+
56−import Data.Binary
60+import Data.Binary
57−import Data.Binary.Put
58−import Data.Binary.Get
61+import Data.Binary.Get
62+import Data.Binary.Put
59−import qualified Data.ByteString as B
63+import qualified Data.ByteString as B
60−import qualified Data.ByteString.Internal as BI
64+import qualified Data.ByteString.Internal as BI
61−import qualified Data.ByteString.Lazy as BL
65+import qualified Data.ByteString.Lazy as BL
62−import qualified Data.ByteString.Unsafe as BU
66+import qualified Data.ByteString.Unsafe as BU
63−
67+import Data.Text (Text)
68+import qualified Data.Text.Encoding as T
69+
64−import Data.UUID.Types.Internal.Builder
70+import Data.UUID.Types.Internal.Builder
65−
71+
66−import System.Random
72+import System.Random (Random (..), uniform)
67−
73+import System.Random.Stateful (Uniform (..), uniformWord64)
68−
74+
69−-- |The UUID type. A 'Random' instance is provided which produces
75+import Language.Haskell.TH.Syntax (Lift)
70−-- version 4 UUIDs as specified in RFC 4122. The 'Storable' and
76+
71−-- 'Binary' instances are compatible with RFC 4122, storing the fields
77+-- | Type representing <https://en.wikipedia.org/wiki/UUID Universally Unique Identifiers (UUID)> as specified in
72−-- in network order as 16 bytes.
78+-- <http://tools.ietf.org/html/rfc4122 RFC 4122>.
73−data UUID
79+data UUID = UUID {-# UNPACK #-} !Word64 {-# UNPACK #-} !Word64
74− = UUID
75− {-# UNPACK #-} !Word32
76− {-# UNPACK #-} !Word32
77− {-# UNPACK #-} !Word32
78− {-# UNPACK #-} !Word32
79− deriving (Eq, Ord, Typeable)
80+ deriving (Eq, Ord)
80{-
81{-
82+ Prior to uuid-types-1.0.4:
83+ !Word32 !Word32 !Word32 !Word32
81 Other representations that we tried are:
84 Other representations that we tried are:
82 Mimic V1 structure: !Word32 !Word16 !Word16 !Word16
85 Mimic V1 structure: !Word32 !Word16 !Word16 !Word16
83 !Word8 !Word8 !Word8 !Word8 !Word8 !Word8
86 !Word8 !Word8 !Word8 !Word8 !Word8 !Word8
@@ -89,40 +92,75 @@ data UUID
89 None was as fast, overall, as the representation used here.
92 None was as fast, overall, as the representation used here.
90-}
93-}
91
94
92−-- | Covert a 'UUID' into a sequence of 'Word32' values.
95+-- | Convert a 'UUID' into a sequence of 'Word32' values.
93-- Useful for when you need to serialize a UUID and
96-- Useful for when you need to serialize a UUID and
94-- neither 'Storable' nor 'Binary' are appropriate.
97-- neither 'Storable' nor 'Binary' are appropriate.
95−-- Introduced in version 1.2.2.
98+--
99+-- >>> toWords <$> fromString "550e8400-e29b-41d4-a716-446655440000"
100+-- Just (1427014656,3801825748,2803254374,1430519808)
101+--
102+-- See also 'toWords64'.
103+--
104+-- /Since: @uuid-1.2.2@/
105+--
106+-- @since 1.0.0
96toWords :: UUID -> (Word32, Word32, Word32, Word32)
107toWords :: UUID -> (Word32, Word32, Word32, Word32)
97−toWords (UUID w1 w2 w3 w4) = (w1, w2, w3, w4)
108+toWords (UUID w12 w34) = (w1, w2, w3, w4)
109+ where
110+ w1 = fromIntegral (w12 `unsafeShiftR` 32)
111+ w2 = fromIntegral w12
112+ w3 = fromIntegral (w34 `unsafeShiftR` 32)
113+ w4 = fromIntegral w34
98
114
99-- | Create a 'UUID' from a sequence of 'Word32'. The
115-- | Create a 'UUID' from a sequence of 'Word32'. The
100−-- opposite of 'toWords'. Useful when you need a total
116+-- inverse of 'toWords'. Useful when you need a total
101-- function for constructing 'UUID' values.
117-- function for constructing 'UUID' values.
102−-- Introduced in version 1.2.2.
118+--
119+-- See also 'fromWords64'.
120+--
121+-- /Since: @uuid-1.2.2@/
122+--
123+-- @since 1.0.0
103fromWords :: Word32 -> Word32 -> Word32 -> Word32 -> UUID
124fromWords :: Word32 -> Word32 -> Word32 -> Word32 -> UUID
104−fromWords = UUID
125+fromWords w1 w2 w3 w4 = UUID (w32to64 w1 w2) (w32to64 w3 w4)
126+
127+-- | Convert a 'UUID' into a pair of 'Word64's.
128+--
129+-- >>> toWords64 <$> fromString "550e8400-e29b-41d4-a716-446655440000"
130+-- Just (6128981282234515924,12039885860129472512)
131+--
132+-- See also 'toWords'.
133+--
134+-- @since 1.0.4
135+toWords64 :: UUID -> (Word64, Word64)
136+toWords64 (UUID w12 w34) = (w12,w34)
137+
138+-- | Create a 'UUID' from a pair of 'Word64's.
139+--
140+-- Inverse of 'toWords64'. See also 'fromWords'.
141+--
142+-- @since 1.0.4
143+fromWords64 :: Word64 -> Word64 -> UUID
144+fromWords64 = UUID
105
145
106data UnpackedUUID =
146data UnpackedUUID =
107 UnpackedUUID {
147 UnpackedUUID {
108− time_low :: Word32 -- 0-3
148+ time_low :: Word32 -- 0-3
109− , time_mid :: Word16 -- 4-5
149+ , time_mid :: Word16 -- 4-5
110 , time_hi_and_version :: Word16 -- 6-7
150 , time_hi_and_version :: Word16 -- 6-7
111− , clock_seq_hi_res :: Word8 -- 8
151+ , clock_seq_hi_res :: Word8 -- 8
112− , clock_seq_low :: Word8 -- 9
152+ , clock_seq_low :: Word8 -- 9
113− , node_0 :: Word8
153+ , node_0 :: Word8
114− , node_1 :: Word8
154+ , node_1 :: Word8
115− , node_2 :: Word8
155+ , node_2 :: Word8
116− , node_3 :: Word8
156+ , node_3 :: Word8
117− , node_4 :: Word8
157+ , node_4 :: Word8
118− , node_5 :: Word8
158+ , node_5 :: Word8
119 }
159 }
120 deriving (Read, Show, Eq, Ord)
160 deriving (Read, Show, Eq, Ord)
121
161
122unpack :: UUID -> UnpackedUUID
162unpack :: UUID -> UnpackedUUID
123−unpack (UUID w0 w1 w2 w3) =
163+unpack (UUID w0 w1) = build /-/ w0 /-/ w1
124− build /-/ w0 /-/ w1 /-/ w2 /-/ w3
125−
126 where
164 where
127 build x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF =
165 build x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF =
128 UnpackedUUID {
166 UnpackedUUID {
@@ -157,23 +195,26 @@ pack unpacked =
157
195
158-- |Build a Word32 from four Word8 values, presented in big-endian order
196-- |Build a Word32 from four Word8 values, presented in big-endian order
159word :: Word8 -> Word8 -> Word8 -> Word8 -> Word32
197word :: Word8 -> Word8 -> Word8 -> Word8 -> Word32
160−word a b c d = (fromIntegral a `shiftL` 24)
198+word a b c d = (fromIntegral a `unsafeShiftL` 24)
161− .|. (fromIntegral b `shiftL` 16)
199+ .|. (fromIntegral b `unsafeShiftL` 16)
162− .|. (fromIntegral c `shiftL` 8)
200+ .|. (fromIntegral c `unsafeShiftL` 8)
163− .|. (fromIntegral d )
201+ .|. (fromIntegral d )
164
202
165−-- |Extract a Word8 from a Word32. Bytes, high to low, are numbered from 3 to 0,
203+-- |Extract a Word8 from a Word64. Bytes, high to low, are numbered from 7 to 0,
166−byte :: Int -> Word32 -> Word8
204+byte :: Int -> Word64 -> Word8
167byte i w = fromIntegral (w `shiftR` (i * 8))
205byte i w = fromIntegral (w `shiftR` (i * 8))
168
206
169-- |Build a Word16 from two Word8 values, presented in big-endian order.
207-- |Build a Word16 from two Word8 values, presented in big-endian order.
170w8to16 :: Word8 -> Word8 -> Word16
208w8to16 :: Word8 -> Word8 -> Word16
171w8to16 w0s w1s =
209w8to16 w0s w1s =
172− (w0 `shiftL` 8) .|. w1
210+ (w0 `unsafeShiftL` 8) .|. w1
173 where
211 where
174 w0 = fromIntegral w0s
212 w0 = fromIntegral w0s
175 w1 = fromIntegral w1s
213 w1 = fromIntegral w1s
176
214
215+-- | Construct 'Word64' from low/high 'Word32's
216+w32to64 :: Word32 -> Word32 -> Word64
217+w32to64 w0 w1 = (fromIntegral w0 `unsafeShiftL` 32) .|. (fromIntegral w1)
177
218
178-- |Make a UUID from sixteen Word8 values
219-- |Make a UUID from sixteen Word8 values
179makeFromBytes :: Word8 -> Word8 -> Word8 -> Word8
220makeFromBytes :: Word8 -> Word8 -> Word8 -> Word8
@@ -182,16 +223,12 @@ makeFromBytes :: Word8 -> Word8 -> Word8 -> Word8
182 -> Word8 -> Word8 -> Word8 -> Word8
223 -> Word8 -> Word8 -> Word8 -> Word8
183 -> UUID
224 -> UUID
184makeFromBytes b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf
225makeFromBytes b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf
185− = UUID w0 w1 w2 w3
226+ = fromWords w0 w1 w2 w3
186 where w0 = word b0 b1 b2 b3
227 where w0 = word b0 b1 b2 b3
187 w1 = word b4 b5 b6 b7
228 w1 = word b4 b5 b6 b7
188 w2 = word b8 b9 ba bb
229 w2 = word b8 b9 ba bb
189 w3 = word bc bd be bf
230 w3 = word bc bd be bf
190
231
191−-- |Make a UUID from four Word32 values
192−makeFromWords :: Word32 -> Word32 -> Word32 -> Word32 -> UUID
193−makeFromWords = UUID
194−
195-- |A Builder for constructing a UUID of a given version.
232-- |A Builder for constructing a UUID of a given version.
196buildFromBytes :: Word8
233buildFromBytes :: Word8
197 -> Word8 -> Word8 -> Word8 -> Word8
234 -> Word8 -> Word8 -> Word8 -> Word8
@@ -204,20 +241,20 @@ buildFromBytes v b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf =
204 where b6' = b6 .&. 0x0f .|. (v `shiftL` 4)
241 where b6' = b6 .&. 0x0f .|. (v `shiftL` 4)
205 b8' = b8 .&. 0x3f .|. 0x80
242 b8' = b8 .&. 0x3f .|. 0x80
206
243
207−-- |Build a UUID of a given version from Word32 values.
244+-- |Build a UUID of a given version from 'Word32' values.
208buildFromWords :: Word8 -> Word32 -> Word32 -> Word32 -> Word32 -> UUID
245buildFromWords :: Word8 -> Word32 -> Word32 -> Word32 -> Word32 -> UUID
209−buildFromWords v w0 w1 w2 w3 = makeFromWords w0 w1' w2' w3
246+buildFromWords v w0 w1 w2 w3 = fromWords w0 w1' w2' w3
210 where w1' = w1 .&. 0xffff0fff .|. ((fromIntegral v) `shiftL` 12)
247 where w1' = w1 .&. 0xffff0fff .|. ((fromIntegral v) `shiftL` 12)
211 w2' = w2 .&. 0x3fffffff .|. 0x80000000
248 w2' = w2 .&. 0x3fffffff .|. 0x80000000
212
249
213
250
214-- |Return the bytes that make up the UUID
251-- |Return the bytes that make up the UUID
215toList :: UUID -> [Word8]
252toList :: UUID -> [Word8]
216−toList (UUID w0 w1 w2 w3) =
253+toList (UUID w0 w1) =
217− [byte 3 w0, byte 2 w0, byte 1 w0, byte 0 w0,
254+ [byte 7 w0, byte 6 w0, byte 5 w0, byte 4 w0,
218− byte 3 w1, byte 2 w1, byte 1 w1, byte 0 w1,
255+ byte 3 w0, byte 2 w0, byte 1 w0, byte 0 w0,
219− byte 3 w2, byte 2 w2, byte 1 w2, byte 0 w2,
256+ byte 7 w1, byte 6 w1, byte 5 w1, byte 4 w1,
220− byte 3 w3, byte 2 w3, byte 1 w3, byte 0 w3]
257+ byte 3 w1, byte 2 w1, byte 1 w1, byte 0 w1]
221
258
222-- |Construct a UUID from a list of Word8. Returns Nothing if the list isn't
259-- |Construct a UUID from a list of Word8. Returns Nothing if the list isn't
223-- exactly sixteen bytes long
260-- exactly sixteen bytes long
@@ -238,10 +275,10 @@ null = (== nil)
238 -- null (UUID 0 0 0 0) = True
275 -- null (UUID 0 0 0 0) = True
239 -- null _ = False
276 -- null _ = False
240
277
241−-- |The nil UUID, as defined in RFC 4122.
278+-- |The 'nil' UUID, as defined in <http://tools.ietf.org/html/rfc4122 RFC 4122>.
242−-- It is a UUID of all zeros. @'null' u@ iff @'u' == 'nil'@.
279+-- It is a UUID of all zeros. @'null' u@ /iff/ @'u' == 'nil'@.
243nil :: UUID
280nil :: UUID
244−nil = UUID 0 0 0 0
281+nil = UUID 0 0
245
282
246-- |Extract a UUID from a 'ByteString' in network byte order.
283-- |Extract a UUID from a 'ByteString' in network byte order.
247-- The argument must be 16 bytes long, otherwise 'Nothing' is returned.
284-- The argument must be 16 bytes long, otherwise 'Nothing' is returned.
@@ -249,6 +286,8 @@ fromByteString :: BL.ByteString -> Maybe UUID
249fromByteString = fromList . BL.unpack
286fromByteString = fromList . BL.unpack
250
287
251-- |Encode a UUID into a 'ByteString' in network order.
288-- |Encode a UUID into a 'ByteString' in network order.
289+--
290+-- This uses the same encoding as the 'Binary' instance.
252toByteString :: UUID -> BL.ByteString
291toByteString :: UUID -> BL.ByteString
253toByteString = BL.pack . toList
292toByteString = BL.pack . toList
254
293
@@ -256,9 +295,8 @@ toByteString = BL.pack . toList
256-- The hyphens may not be omitted.
295-- The hyphens may not be omitted.
257-- Example:
296-- Example:
258--
297--
259−-- @
260−-- fromString \"c2cc10e1-57d6-4b6f-9899-38d972112d8c\"
298+-- >>> fromString "c2cc10e1-57d6-4b6f-9899-38d972112d8c"
261−-- @
299+-- Just c2cc10e1-57d6-4b6f-9899-38d972112d8c
262--
300--
263-- Hex digits may be upper or lower-case.
301-- Hex digits may be upper or lower-case.
264fromString :: String -> Maybe UUID
302fromString :: String -> Maybe UUID
@@ -273,7 +311,7 @@ fromString' s0 = do
273 (w2, s3) <- hexWord s2
311 (w2, s3) <- hexWord s2
274 (w3, s4) <- hexWord s3
312 (w3, s4) <- hexWord s3
275 if s4 /= "" then Nothing
313 if s4 /= "" then Nothing
276− else Just $ UUID w0 w1 w2 w3
314+ else Just $ fromWords w0 w1 w2 w3
277 where hexWord :: String -> Maybe (Word32, String)
315 where hexWord :: String -> Maybe (Word32, String)
278 hexWord s = Just (0, s) >>= hexByte >>= hexByte
316 hexWord s = Just (0, s) >>= hexByte >>= hexByte
279 >>= hexByte >>= hexByte
317 >>= hexByte >>= hexByte
@@ -290,21 +328,39 @@ fromString' s0 = do
290-- | Convert a UUID into a hypenated string using lower-case letters.
328-- | Convert a UUID into a hypenated string using lower-case letters.
291-- Example:
329-- Example:
292--
330--
293−-- @
294−-- toString \<$\> fromString \"550e8400-e29b-41d4-a716-446655440000\"
331+-- >>> toString <$> fromString "550e8400-e29b-41d4-a716-446655440000"
295−-- @
332+-- Just "550e8400-e29b-41d4-a716-446655440000"
333+--
334+--
296toString :: UUID -> String
335toString :: UUID -> String
297−toString (UUID w0 w1 w2 w3) = hexw w0 $ hexw' w1 $ hexw' w2 $ hexw w3 ""
336+toString uuid = hexw0 w0 $ hexw1 w1 ""
298− where hexw :: Word32 -> String -> String
337+ where hexw0 :: Word64 -> String -> String
338+ hexw0 w s = hexn w 60 : hexn w 56 : hexn w 52 : hexn w 48
339+ : hexn w 44 : hexn w 40 : hexn w 36 : hexn w 32
299− hexw w s = hexn w 28 : hexn w 24 : hexn w 20 : hexn w 16
340+ : '-' : hexn w 28 : hexn w 24 : hexn w 20 : hexn w 16
300− : hexn w 12 : hexn w 8 : hexn w 4 : hexn w 0 : s
341+ : '-' : hexn w 12 : hexn w 8 : hexn w 4 : hexn w 0
342+ : s
343+
344+ hexw1 :: Word64 -> String -> String
345+ hexw1 w s = '-' : hexn w 60 : hexn w 56 : hexn w 52 : hexn w 48
346+ : '-' : hexn w 44 : hexn w 40 : hexn w 36 : hexn w 32
347+ : hexn w 28 : hexn w 24 : hexn w 20 : hexn w 16
348+ : hexn w 12 : hexn w 8 : hexn w 4 : hexn w 0
349+ : s
350+
351+ hexn :: Word64 -> Int -> Char
352+ hexn w r = intToDigit $ fromIntegral ((w `shiftR` r) .&. 0xf)
301
353
302− hexw' :: Word32 -> String -> String
354+ (w0,w1) = toWords64 uuid
303− hexw' w s = '-' : hexn w 28 : hexn w 24 : hexn w 20 : hexn w 16
304− : '-' : hexn w 12 : hexn w 8 : hexn w 4 : hexn w 0 : s
305
355
306− hexn :: Word32 -> Int -> Char
356+-- | If the passed in `Text` can be parsed as an ASCII representation of
307− hexn w r = intToDigit $ fromIntegral ((w `shiftR` r) .&. 0xf)
357+-- a `UUID`, it will be. The hyphens may not be omitted.
358+fromText :: Text -> Maybe UUID
359+fromText = fromASCIIBytes . T.encodeUtf8
360+
361+-- | Convert a UUID into a hyphentated string using lower-case letters.
362+toText :: UUID -> Text
363+toText = T.decodeLatin1 . toASCIIBytes
308
364
309-- | Convert a UUID into a hyphentated string using lower-case letters, packed
365-- | Convert a UUID into a hyphentated string using lower-case letters, packed
310-- as ASCII bytes into `B.ByteString`.
366-- as ASCII bytes into `B.ByteString`.
@@ -399,49 +455,30 @@ fromASCIIBytes bs = do
399-- | Similar to `toASCIIBytes` except we produce a lazy `BL.ByteString`.
455-- | Similar to `toASCIIBytes` except we produce a lazy `BL.ByteString`.
400toLazyASCIIBytes :: UUID -> BL.ByteString
456toLazyASCIIBytes :: UUID -> BL.ByteString
401toLazyASCIIBytes =
457toLazyASCIIBytes =
402−#if MIN_VERSION_bytestring(0,10,0)
403 BL.fromStrict
458 BL.fromStrict
404−#else
405− BL.fromChunks . return
406−#endif
407 . toASCIIBytes
459 . toASCIIBytes
408
460
409-- | Similar to `fromASCIIBytes` except parses from a lazy `BL.ByteString`.
461-- | Similar to `fromASCIIBytes` except parses from a lazy `BL.ByteString`.
410fromLazyASCIIBytes :: BL.ByteString -> Maybe UUID
462fromLazyASCIIBytes :: BL.ByteString -> Maybe UUID
411fromLazyASCIIBytes bs =
463fromLazyASCIIBytes bs =
412− if BL.length bs == 36 then fromASCIIBytes (
464+ if BL.length bs == 36 then fromASCIIBytes (BL.toStrict bs) else Nothing
413−#if MIN_VERSION_bytestring(0,10,0)
414− BL.toStrict bs
415−#else
416− B.concat $ BL.toChunks bs
417−#endif
418− ) else Nothing
419
465
420--
466--
421-- Class Instances
467-- Class Instances
422--
468--
423
469
470+-- | This 'Random' instance produces __insecure__ version 4 UUIDs as
471+-- specified in <http://tools.ietf.org/html/rfc4122 RFC 4122>.
424instance Random UUID where
472instance Random UUID where
425− random g = (fromGenNext w0 w1 w2 w3 w4, g4)
473+ random = uniform
426− where (w0, g0) = next g
427− (w1, g1) = next g0
428− (w2, g2) = next g1
429− (w3, g3) = next g2
430− (w4, g4) = next g3
431 randomR _ = random -- range is ignored
474 randomR _ = random -- range is ignored
432
475
433−-- |Build a UUID from the results of five calls to next on a StdGen.
476+-- @since 1.0.4
434−-- While next on StdGet returns an Int, it doesn't provide 32 bits of
477+instance Uniform UUID where
435−-- randomness. This code relies on at last 28 bits of randomness in the
478+ uniformM gen = do
436−-- and optimizes its use so as to make only five random values, not six.
479+ w0 <- uniformWord64 gen
437−fromGenNext :: Int -> Int -> Int -> Int -> Int -> UUID
480+ w1 <- uniformWord64 gen
438−fromGenNext w0 w1 w2 w3 w4 =
439− buildFromBytes 4 /-/ (ThreeByte w0)
481+ pure $ buildFromBytes 4 /-/ w0 /-/ w1
440− /-/ (ThreeByte w1)
441− /-/ w2 -- use all 4 bytes because we know the version
442− -- field will "cover" the upper, non-random bits
443− /-/ (ThreeByte w3)
444− /-/ (ThreeByte w4)
445
482
446-- |A ByteSource to extract only three bytes from an Int, since next on StdGet
483-- |A ByteSource to extract only three bytes from an Int, since next on StdGet
447-- only returns 31 bits of randomness.
484-- only returns 31 bits of randomness.
@@ -449,24 +486,29 @@ type instance ByteSink ThreeByte g = Takes3Bytes g
449newtype ThreeByte = ThreeByte Int
486newtype ThreeByte = ThreeByte Int
450instance ByteSource ThreeByte where
487instance ByteSource ThreeByte where
451 f /-/ (ThreeByte w) = f b1 b2 b3
488 f /-/ (ThreeByte w) = f b1 b2 b3
452− where b1 = fromIntegral (w `shiftR` 16)
489+ where b1 = fromIntegral (w `unsafeShiftR` 16)
453− b2 = fromIntegral (w `shiftR` 8)
490+ b2 = fromIntegral (w `unsafeShiftR` 8)
454 b3 = fromIntegral w
491 b3 = fromIntegral w
455
492
456instance NFData UUID where
493instance NFData UUID where
457− rnf = rnf . toWords
494+ rnf = flip seq ()
458
495
459instance Hashable UUID where
496instance Hashable UUID where
460− hash (UUID w0 w1 w2 w3) =
497+ hash (toWords -> (w0,w1,w2,w3)) =
461 hash w0 `hashWithSalt` w1
498 hash w0 `hashWithSalt` w1
462 `hashWithSalt` w2
499 `hashWithSalt` w2
463 `hashWithSalt` w3
500 `hashWithSalt` w3
464− hashWithSalt s (UUID w0 w1 w2 w3) =
501+ hashWithSalt s (toWords -> (w0,w1,w2,w3)) =
465 s `hashWithSalt` w0
502 s `hashWithSalt` w0
466 `hashWithSalt` w1
503 `hashWithSalt` w1
467 `hashWithSalt` w2
504 `hashWithSalt` w2
468 `hashWithSalt` w3
505 `hashWithSalt` w3
469
506
507+-- | Pretty prints a 'UUID' (without quotation marks). See also 'toString'.
508+--
509+-- >>> show nil
510+-- "00000000-0000-0000-0000-000000000000"
511+--
470instance Show UUID where
512instance Show UUID where
471 show = toString
513 show = toString
472
514
@@ -477,7 +519,7 @@ instance Read UUID where
477 Nothing -> []
519 Nothing -> []
478 Just u -> [(u,drop 36 noSpaces)]
520 Just u -> [(u,drop 36 noSpaces)]
479
521
480−
522+-- | This 'Storable' instance uses the memory layout as described in <http://tools.ietf.org/html/rfc4122 RFC 4122>, but in contrast to the 'Binary' instance, __the fields are stored in host byte order__.
481instance Storable UUID where
523instance Storable UUID where
482 sizeOf _ = 16
524 sizeOf _ = 16
483 alignment _ = 4
525 alignment _ = 4
@@ -514,10 +556,10 @@ instance Storable UUID where
514 pokeByteOff p (off+14) x9
556 pokeByteOff p (off+14) x9
515 pokeByteOff p (off+15) x10
557 pokeByteOff p (off+15) x10
516
558
559+-- | This 'Binary' instance is compatible with <http://tools.ietf.org/html/rfc4122 RFC 4122>, storing the fields in network order as 16 bytes.
517instance Binary UUID where
560instance Binary UUID where
518− put (UUID w0 w1 w2 w3) =
561+ put (UUID w0 w1) = putWord64be w0 >> putWord64be w1
519− putWord32be w0 >> putWord32be w1 >> putWord32be w2 >> putWord32be w3
562+ get = liftM2 UUID getWord64be getWord64be
520− get = liftM4 UUID getWord32be getWord32be getWord32be getWord32be
521
563
522
564
523-- My goal with this instance was to make it work just enough to do what
565-- My goal with this instance was to make it work just enough to do what
@@ -530,7 +572,4 @@ instance Data UUID where
530uuidType :: DataType
572uuidType :: DataType
531uuidType = mkNoRepType "Data.UUID.Types.UUID"
573uuidType = mkNoRepType "Data.UUID.Types.UUID"
532
574
533−#if !(MIN_VERSION_base(4,2,0))
575+deriving instance Lift UUID
534−mkNoRepType :: String -> DataType
535−mkNoRepType = mkNorepType
536−#endif
uuid-types/Data/UUID/Types/Internal/Builder.hs → uuid-types/src/Data/UUID/Types/Internal/Builder.hsrenamed+17−1
@@ -1,6 +1,9 @@
1{-# LANGUAGE TypeFamilies #-}
1{-# LANGUAGE TypeFamilies #-}
2+{-# LANGUAGE Unsafe #-}
2
3
4+{-# OPTIONS_HADDOCK hide #-}
5+
3−-- Module : Data.UUID.Types.Internal.Builder
6+-- | Module : Data.UUID.Types.Internal.Builder
4-- Copyright : (c) 2009 Mark Lentczner
7-- Copyright : (c) 2009 Mark Lentczner
5--
8--
6-- License : BSD-style
9-- License : BSD-style
@@ -46,6 +49,7 @@ type Takes1Byte g = Word8 -> g
46type Takes2Bytes g = Word8 -> Word8 -> g
49type Takes2Bytes g = Word8 -> Word8 -> g
47type Takes3Bytes g = Word8 -> Word8 -> Word8 -> g
50type Takes3Bytes g = Word8 -> Word8 -> Word8 -> g
48type Takes4Bytes g = Word8 -> Word8 -> Word8 -> Word8 -> g
51type Takes4Bytes g = Word8 -> Word8 -> Word8 -> Word8 -> g
52+type Takes8Bytes g = Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> Word8 -> g
49
53
50-- | Type of function that a given ByteSource needs.
54-- | Type of function that a given ByteSource needs.
51-- This function must take as many Word8 arguments as the ByteSource provides
55-- This function must take as many Word8 arguments as the ByteSource provides
@@ -53,6 +57,7 @@ type family ByteSink w g
53type instance ByteSink Word8 g = Takes1Byte g
57type instance ByteSink Word8 g = Takes1Byte g
54type instance ByteSink Word16 g = Takes2Bytes g
58type instance ByteSink Word16 g = Takes2Bytes g
55type instance ByteSink Word32 g = Takes4Bytes g
59type instance ByteSink Word32 g = Takes4Bytes g
60+type instance ByteSink Word64 g = Takes8Bytes g
56type instance ByteSink Int g = Takes4Bytes g
61type instance ByteSink Int g = Takes4Bytes g
57
62
58
63
@@ -80,6 +85,17 @@ instance ByteSource Word32 where
80 b3 = fromIntegral (w `shiftR` 8)
85 b3 = fromIntegral (w `shiftR` 8)
81 b4 = fromIntegral w
86 b4 = fromIntegral w
82
87
88+instance ByteSource Word64 where
89+ f /-/ w = f b1 b2 b3 b4 b5 b6 b7 b8
90+ where b1 = fromIntegral (w `shiftR` 56)
91+ b2 = fromIntegral (w `shiftR` 48)
92+ b3 = fromIntegral (w `shiftR` 40)
93+ b4 = fromIntegral (w `shiftR` 32)
94+ b5 = fromIntegral (w `shiftR` 24)
95+ b6 = fromIntegral (w `shiftR` 16)
96+ b7 = fromIntegral (w `shiftR` 8)
97+ b8 = fromIntegral w
98+
83instance ByteSource Int where
99instance ByteSource Int where
84 f /-/ w = f b1 b2 b3 b4
100 f /-/ w = f b1 b2 b3 b4
85 where b1 = fromIntegral (w `shiftR` 24)
101 where b1 = fromIntegral (w `shiftR` 24)
uuid-types/tests/BenchByteString.hsdeleted−82
@@ -1,82 +0,0 @@
1−import Control.Applicative ((<*>))
2−import Data.Functor ((<$>))
3−
4−import Data.ByteString (ByteString)
5−import qualified Data.ByteString.Char8 as BC8
6−import System.Random
7−import Test.QuickCheck
8−
9−import Criterion
10−import Criterion.Main
11−
12−import Data.UUID.Types
13−
14−instance Arbitrary UUID where
15− arbitrary =
16− fromWords <$> arbitrary <*> arbitrary <*> arbitrary <*> arbitrary
17−
18−-- Testing what we do in the codebase
19−fromASCIIBytes_naive :: ByteString -> Maybe UUID
20−fromASCIIBytes_naive = fromString . BC8.unpack
21−
22−toASCIIBytes_naive :: UUID -> ByteString
23−toASCIIBytes_naive = BC8.pack . toString
24−
25−randomUUIDs :: IO [UUID]
26−randomUUIDs = sample' arbitrary
27−
28−randomCorrect :: IO [String]
29−randomCorrect = map toString <$> randomUUIDs
30−
31−randomSlightlyWrong :: IO [String]
32−randomSlightlyWrong = mapM screw =<< randomCorrect
33− where
34− screw s = do
35− ix <- randomRIO (0, length s - 1)
36− return (take ix s ++ "x" ++ drop (ix + 1) s)
37−
38−randomVeryWrong :: IO [String]
39−randomVeryWrong = sample' arbitrary
40−
41−main :: IO ()
42−main = do
43− uuids <- randomUUIDs
44− correct <- randomCorrect
45− let correctBytes = map BC8.pack correct
46− slightlyWrong <- randomSlightlyWrong
47− let slightlyWrongBytes = map BC8.pack slightlyWrong
48− veryWrong <- randomVeryWrong
49− let veryWrongBytes = map BC8.pack veryWrong
50−
51− defaultMain
52− [ bgroup "decoding"
53− [ bcompare
54− [ bgroup "correct"
55− [ bench "fromASCIIBytes" (nf (map fromASCIIBytes) correctBytes)
56− , bench "fromString" (nf (map fromString) correct)
57− , bench "fromASCIIBytes_naive" (nf (map fromASCIIBytes_naive) correctBytes)
58− ]
59− ]
60− , bcompare
61− [ bgroup "slightly wrong"
62− [ bench "fromASCIIBytes" (nf (map fromASCIIBytes) slightlyWrongBytes)
63− , bench "fromString" (nf (map fromString) slightlyWrong)
64− , bench "fromASCIIBytes_naive" (nf (map fromASCIIBytes_naive) slightlyWrongBytes)
65− ]
66− ]
67− , bcompare
68− [ bgroup "very wrong"
69− [ bench "fromASCIIBytes" (nf (map fromASCIIBytes) veryWrongBytes)
70− , bench "fromString" (nf (map fromString) veryWrong)
71− , bench "fromASCIIBytes_naive" (nf (map fromASCIIBytes_naive) veryWrongBytes)
72− ]
73− ]
74− ]
75− , bcompare
76− [ bgroup "encoding"
77− [ bench "toASCIIBytes" (nf (map toASCIIBytes) uuids)
78− , bench "toString" (nf (map toString) uuids)
79− , bench "toASCIIBytes_naive" (nf (map toASCIIBytes_naive) uuids)
80− ]
81− ]
82− ]
uuid-types/tests/TestUUID.hs+71−34
@@ -1,59 +1,92 @@
1{-# LANGUAGE ViewPatterns #-}
1{-# LANGUAGE ViewPatterns #-}
2+{-# LANGUAGE TemplateHaskell #-}
3+
4+{-# OPTIONS_GHC -fno-warn-orphans #-}
5+
6+import Data.Binary (encode)
7+import qualified Data.ByteString.Char8 as BC8
2−import qualified Data.ByteString.Lazy as BL
8+import qualified Data.ByteString.Lazy as BL
3import qualified Data.ByteString.Lazy.Char8 as BL8
9import qualified Data.ByteString.Lazy.Char8 as BL8
4−import qualified Data.ByteString.Char8 as BC8
5−import Data.Char (ord)
10+import Data.Char (ord)
6−import Data.Functor ((<$>))
11+import Data.Functor ((<$>))
7−import Data.Word
8−import qualified Data.UUID.Types as U
12+import qualified Data.UUID.Types as U
13+import Data.Word
9−import Foreign (alloca, peek, poke)
14+import Foreign (alloca, castPtr, peek, poke,
15+ sizeOf)
16+import GHC.ByteOrder (ByteOrder(..), targetByteOrder)
10−import System.IO.Unsafe (unsafePerformIO)
17+import System.IO.Unsafe (unsafePerformIO)
11−import qualified Test.HUnit as H
18+
12−import Test.HUnit hiding (Test)
13−import Test.QuickCheck hiding ((.&.))
19+import Test.QuickCheck (Arbitrary (arbitrary), choose)
14−import Test.Framework (defaultMain, Test)
15−import Test.Framework.Providers.HUnit (hUnitTestToTests)
16−import Test.Framework.Providers.QuickCheck2 (testProperty)
17
20
21+import Test.Tasty (TestTree, defaultMain, testGroup)
22+import Test.Tasty.HUnit (assertBool, testCase, (@=?), (@?=))
23+import Test.Tasty.QuickCheck (testProperty)
18
24
25+
26+-- orphan
19instance Arbitrary U.UUID where
27instance Arbitrary U.UUID where
20 -- the UUID random instance ignores bounds
28 -- the UUID random instance ignores bounds
21 arbitrary = choose (U.nil, U.nil)
29 arbitrary = choose (U.nil, U.nil)
22
30
31+type Test = TestTree
23
32
24−test_null :: H.Test
33+test_null :: Test
25−test_null = H.TestList [
34+test_null =
35+ testCase "nil is null" $
26− "nil is null" ~: assertBool "" (U.null U.nil)
36+ assertBool "" (U.null U.nil)
27− ]
28
37
29−test_nil :: H.Test
38+test_nil :: Test
30−test_nil = H.TestList [
39+test_nil = testGroup "nil" [
31− "nil string" ~: U.toString U.nil @?= "00000000-0000-0000-0000-000000000000",
40+ testCase "nil string" $ U.toString U.nil @?= "00000000-0000-0000-0000-000000000000",
32− "nil bytes" ~: U.toByteString U.nil @?= BL.pack (replicate 16 0)
41+ testCase "nil bytes" $ U.toByteString U.nil @?= BL.pack (replicate 16 0)
33 ]
42 ]
34
43
35−test_conv :: H.Test
44+test_lift :: Test
36−test_conv = H.TestList [
45+test_lift = testCase "TH.Lift" $ do
46+ let uuid = U.fromWords64 123456789 987654321
47+ uuid @?= $( [| uuid |] )
48+
49+test_conv :: Test
50+test_conv = testGroup "conversions" [
37− "conv bytes to string" ~:
51+ testCase "conv bytes to string" $
38 maybe "" (U.toString) (U.fromByteString b16) @?= s16,
52 maybe "" (U.toString) (U.fromByteString b16) @?= s16,
39− "conv string to bytes" ~:
53+ testCase "conv string to bytes" $
40 maybe BL.empty (U.toByteString) (U.fromString s16) @?= b16
54 maybe BL.empty (U.toByteString) (U.fromString s16) @?= b16
41 ]
55 ]
42 where b16 = BL.pack [1..16]
56 where b16 = BL.pack [1..16]
43 s16 = "01020304-0506-0708-090a-0b0c0d0e0f10"
57 s16 = "01020304-0506-0708-090a-0b0c0d0e0f10"
44
58
45-- | Test fromByteString with a fixed-input.
59-- | Test fromByteString with a fixed-input.
46−test_fromByteString :: H.Test
60+test_fromByteString :: Test
47test_fromByteString =
61test_fromByteString =
48− "UUID fromByteString" ~:
62+ testCase "UUID fromByteString" $
49 Just inputUUID @=?
63 Just inputUUID @=?
50− U.fromByteString (BL8.pack "\165\202\133f\217\197H5\153\200\225\241>s\181\226")
64+ U.fromByteString (BL8.pack "\xa5\xca\x85\x66\xd9\xc5\x48\x35\x99\xc8\xe1\xf1\x3e\x73\xb5\xe2")
51
65
52-- | Test fromWords with a fixed-input
66-- | Test fromWords with a fixed-input
53−test_fromWords :: H.Test
67+test_fromWords :: Test
54test_fromWords =
68test_fromWords =
55− "UUID fromWords" ~:
69+ testCase "UUID fromWords" $
56− inputUUID @=? U.fromWords 2781513062 3653584949 2580079089 1047770594
70+ inputUUID @=? U.fromWords 0xa5ca8566 0xd9c54835 0x99c8e1f1 0x3e73b5e2
71+
72+
73+test_Storeable :: Test
74+test_Storeable =
75+ testCase "UUID Storeable(poke)" $
76+ case targetByteOrder of
77+ LittleEndian -> BC8.pack "\x66\x85\xca\xa5\xc5\xd9\x35\x48\x99\xc8\xe1\xf1\x3e\x73\xb5\xe2" @=? pokeAsBS inputUUID
78+ BigEndian -> BC8.pack "\xa5\xca\x85\x66\xd9\xc5\x48\x35\x99\xc8\xe1\xf1\x3e\x73\xb5\xe2" @=? pokeAsBS inputUUID
79+ where
80+ pokeAsBS :: U.UUID -> BC8.ByteString
81+ pokeAsBS uuid = unsafePerformIO $ do
82+ alloca $ \ptr -> do
83+ poke ptr uuid
84+ BC8.packCStringLen (castPtr ptr, sizeOf uuid)
85+
86+test_Binary :: Test
87+test_Binary =
88+ testCase "UUID Binary(encode)" $
89+ (BL8.pack "\xa5\xca\x85\x66\xd9\xc5\x48\x35\x99\xc8\xe1\xf1\x3e\x73\xb5\xe2") @=? encode inputUUID
57
90
58inputUUID :: U.UUID
91inputUUID :: U.UUID
59inputUUID = read "a5ca8566-d9c5-4835-99c8-e1f13e73b5e2"
92inputUUID = read "a5ca8566-d9c5-4835-99c8-e1f13e73b5e2"
@@ -144,13 +177,17 @@ prop_storableRoundTrip =
144main :: IO ()
177main :: IO ()
145main = do
178main = do
146 defaultMain $
179 defaultMain $
180+ testGroup "tests" $
147 concat $
181 concat $
148− [ hUnitTestToTests $ H.TestList [
182+ [ [
149 test_null,
183 test_null,
150 test_nil,
184 test_nil,
185+ test_lift,
151 test_conv,
186 test_conv,
152 test_fromByteString,
187 test_fromByteString,
153− test_fromWords
188+ test_fromWords,
189+ test_Storeable,
190+ test_Binary
154 ]
191 ]
155 , [ prop_stringRoundTrip,
192 , [ prop_stringRoundTrip,
156 prop_readShowRoundTrip,
193 prop_readShowRoundTrip,
uuid-types/tests/summarize-bench-results.pldeleted−14
@@ -1,14 +0,0 @@
1−#!/usr/bin/env perl
2−
3−
4−while(<>) {
5− if (/^benchmarking (.*)$/) {
6− $name = $1;
7− }
8− if (/^mean:\s*([\d.]*) (\w*),/) {
9− $mean = 1 * $1;
10− $units = $2;
11−
12− printf "%-30s %10.2f %2s\n", $name, $mean, $units;
13− }
14−}
uuid-types/uuid-types.cabal+86−76
@@ -1,89 +1,99 @@
1+cabal-version: 1.12
1−Name: uuid-types
2+name: uuid-types
2−Version: 1.0.0
3+version: 1.0.6
4+x-revision: 2
5+copyright:
6+ (c) 2017-2018 Herbert Valerio Riedel
3−Copyright: (c) 2008-2014 Antoine Latter
7+ (c) 2008-2014 Antoine Latter
4−Author: Antoine Latter
5−Maintainer: aslatter@gmail.com
6−License: BSD3
7−License-file: LICENSE
8
8
9−Category: Data
9+author: Antoine Latter
10+maintainer: Oleg Grenrus <oleg.grenrus@iki.fi>
11+license: BSD3
12+license-file: LICENSE
13+category: Data
10−Build-Type: Simple
14+build-type: Simple
11−Cabal-Version: >= 1.8
15+tested-with:
16+ GHC ==8.6.5
17+ || ==8.8.4
18+ || ==8.10.7
19+ || ==9.0.2
20+ || ==9.2.8
21+ || ==9.4.8
22+ || ==9.6.6
23+ || ==9.8.4
24+ || ==9.10.1
25+ || ==9.12.1
12
26
13−Description:
27+synopsis: Type definitions for Universally Unique Identifiers
28+description:
14− This library contains type definitions for Universally Unique Identifiers
29+ This library contains type definitions for
30+ <https://en.wikipedia.org/wiki/UUID Universally Unique Identifiers (UUID)>
31+ (as specified in
32+ <http://tools.ietf.org/html/rfc4122 RFC 4122>)
15− and basic conversion functions.
33+ and basic conversion functions.
34+ .
35+ See also the <https://hackage.haskell.org/package/uuid 'uuid' package>
36+ providing a high-level API for managing the different UUID versions.
16
37
17− See <http://en.wikipedia.org/wiki/UUID> for the general idea.
38+homepage: https://github.com/haskell-hvr/uuid
39+bug-reports: https://github.com/haskell-hvr/uuid/issues
40+extra-source-files: ChangeLog.md
18
41
19−Synopsis: Type definitions for Universally Unique Identifiers
42+source-repository head
43+ type: git
44+ location: https://github.com/haskell-hvr/uuid.git
45+ subdir: uuid-types
20
46
21−Homepage: https://github.com/aslatter/uuid
47+library
22−Bug-Reports: https://github.com/aslatter/uuid/issues
48+ build-depends:
49+ base >=4.12.0.0 && <5
50+ , binary >=0.8.6.0 && <0.9
51+ , bytestring >=0.10.8.2 && <0.13
52+ , deepseq >=1.4.4.0 && <1.6
53+ , hashable >=1.4.4.0 && <1.6
54+ , random >=1.2.1.2 && <1.3
55+ , template-haskell >=2.14.0.0 && <2.24
56+ , text >=1.2.3.0 && <1.3 || >=2.0 && <2.2
23
57
24−Extra-Source-Files:
58+ exposed-modules: Data.UUID.Types
25− CHANGES
26− CONTRIBUTORS
27
59
60+ -- Exposed for companion projects; *NOT* part of the official API:
61+ exposed-modules:
62+ Data.UUID.Types.Internal
63+ Data.UUID.Types.Internal.Builder
28
64
29−Library
65+ default-language: Haskell2010
30− Build-Depends: base >=3 && < 5,
66+ other-extensions:
31− binary >= 0.4 && < 0.8,
67+ DeriveDataTypeable
32− bytestring >= 0.9 && < 1.1,
68+ TypeFamilies
33− deepseq >= 1.3 && < 1.5,
34− hashable (>= 1.1.1.0 && < 1.2.0) || (>= 1.2.1 && < 1.3),
35− random >= 1.0.1 && < 1.2
36
69
37− Exposed-Modules:
70+ ghc-options: -Wall
38− Data.UUID.Types
71+ hs-source-dirs: src
39− -- Exposed for companion projects; *NOT* part of the official API:
40− Data.UUID.Types.Internal.Builder
41− Data.UUID.Types.Internal
42
72
43− Extensions: DeriveDataTypeable
73+test-suite testuuid
44− Ghc-Options: -Wall
74+ type: exitcode-stdio-1.0
75+ main-is: TestUUID.hs
76+ hs-source-dirs: tests
77+ default-language: Haskell2010
78+ other-extensions: ViewPatterns
79+ ghc-options: -Wall
80+ if impl(ghc >= 8.10)
81+ ghc-options: -Wunused-packages
45
82
46−source-repository head
83+ -- inherited constraints
47− type: git
84+ build-depends:
48− location: https://github.com/aslatter/uuid.git
85+ base
86+ , binary
87+ , bytestring
88+ , template-haskell
89+ , uuid-types
49
90
50−Test-Suite testuuid
91+ -- deps w/o inherited constraints
51− Type: exitcode-stdio-1.0
92+ build-depends:
52− Main-is: TestUUID.hs
53− Hs-source-dirs: tests
54− Extensions: DeriveDataTypeable
55− Ghc-Options: -Wall -fno-warn-orphans
56− Build-Depends: base >= 3 && < 5,
57− uuid-types,
58− bytestring >= 0.9 && < 1.1,
59− HUnit >=1.2 && < 1.3,
60− QuickCheck >=2.4 && < 2.8,
93+ QuickCheck >=2.14.2 && <2.16
61− test-framework == 0.8.*,
94+ , tasty >=1.4.0.1 && <1.6
62− test-framework-hunit == 0.3.*,
95+ , tasty-hunit >=0.10 && <0.11
63− test-framework-quickcheck2 == 0.3.*
96+ , tasty-quickcheck >=0.10 && <0.12
64
97
65−benchmark benchmark
98+ if !impl(ghc >=8.4)
66− Type: exitcode-stdio-1.0
99+ build-depends: ghc-byteorder >=4.11 && <4.12
67− Main-is: BenchUUID.hs
68− Hs-source-dirs: tests
69− Extensions: DeriveDataTypeable, CPP
70− Ghc-Options: -Wall -fno-warn-orphans
71− Build-depends: base == 4.*,
72− uuid-types,
73− bytestring >= 0.9 && < 1.1,
74− containers >= 0.4 && < 0.6,
75− criterion >= 0.4 && < 0.9,
76− deepseq >= 1.1 && < 1.4,
77− random >= 1.0.1 && < 1.2
78−
79−benchmark benchbytestring
80− Type: exitcode-stdio-1.0
81− Hs-Source-Dirs: tests
82− Main-Is: BenchByteString.hs
83− Ghc-Options: -threaded -rtsopts -Wall -O2 -fno-warn-orphans
84− Build-Depends: base >= 4 && < 5
85− , uuid-types
86− , bytestring >= 0.10
87− , criterion >= 0.8
88− , random >= 1.0
89− , QuickCheck >= 2
uuid/CHANGES → uuid/CHANGES.mdrenamed+62−22
@@ -1,3 +1,43 @@
1+1.3.16
2+
3+- Support GHC-8.6.5...9.10.1
4+
5+1.3.15
6+
7+- Add (Template Haskell) `Lift UUID` instance
8+
9+1.3.14
10+
11+- Use more compact heap object representation which saves 16 bytes on 64bit platforms.
12+- Add `toWords64`/`fromWords64` functions
13+
14+1.3.13
15+
16+- Optimize `V4.nextRandom` (~3x speed increase)
17+- Optimize UUID V3 & V5 generation (~2x speed increase)
18+- Use `cryptohash-md5`/`cryptohash-sha1`/`entropy` instead
19+ of `memory`/`cryptonite` for better performance and stability,
20+ but GHCJS is now no longer supported.
21+- Update cabal-spec to version 1.10
22+
23+1.3.12
24+
25+- Update package dependencies
26+- Use `cryptonite` for crypto
27+- The function `V4.nextRandom` is now implemented with functions from
28+ `Crypto.Random` in package `cryptonite`. This does slow-down random
29+ UUID generation but provides for far greater randomness. The
30+ `Random` instance for `UUID` can be used to re-gain the old
31+ behavior.
32+
33+1.3.11
34+
35+- Add `toText`/`fromText`
36+
37+1.3.10
38+
39+- Update dependencies in tests and benchmarks.
40+
11.3.9
411.3.9
2
42
3- Split definition of UUID data type into separate Cabal package to
43- Split definition of UUID data type into separate Cabal package to
@@ -5,11 +45,11 @@
5
45
61.3.8
461.3.8
7
47
8−- Allow building against newer deepseq.
48+- Allow building against newer `deepseq`.
9
49
101.3.7
501.3.7
11
51
12−- Allow building against newer time.
52+- Allow building against newer `time`.
13
53
141.3.6
541.3.6
15
55
@@ -17,58 +57,58 @@
17
57
181.3.5
581.3.5
19
59
20−- Allow building against newer random.
60+- Allow building against newer `random`.
21
61
221.3.4
621.3.4
23
63
24−- Allow building against newer QuickCheck.
64+- Allow building against newer `QuickCheck`.
25
65
261.3.3
661.3.3
27
67
28−- More complex version constrainsts on hashable, to avoid building against
68+- More complex version constraints on `hashable`, to avoid building against
29 versions less than 1.1.1.0 or equal to 1.2.0.*.
69 versions less than 1.1.1.0 or equal to 1.2.0.*.
30
70
311.3.2
711.3.2
32
72
33−- Fix for building against bytestring 0.9.*
73+- Fix for building against `bytestring` 0.9.*
34
74
351.3.1
751.3.1
36
76
37−- Allow building against 'hashable' 1.1.* in addition to 1.2.*
77+- Allow building against `hashable` 1.1.* in addition to 1.2.*
38
78
391.3.0
791.3.0
40
80
41- New functions for parsing and printing UUIDs to and from ASCII BytesStrings
81- New functions for parsing and printing UUIDs to and from ASCII BytesStrings
42−- New module Data.UUID.Util. This module includes the type 'UnpackedUUID',
82+- New module `Data.UUID.Util`. This module includes the type `UnpackedUUID`,
43 whose fields correspond to the UUID fields described in RFC 4122.
83 whose fields correspond to the UUID fields described in RFC 4122.
44−- The Storable instance now stores a UUID in host byte-order instead of
84+- The `Storable` instance now stores a UUID in host byte-order instead of
45 big endian.
85 big endian.
46−- There is now an instance for 'Hashable UUID'.
86+- There is now an instance for `Hashable UUID`.
47
87
481.2.13
881.2.13
49
89
50Benchmark only changes:
90Benchmark only changes:
51
91
52−- Allow criterion 0.8.*
92+- Allow `criterion` 0.8.*
53
93
541.2.12
941.2.12
55
95
56Test only changes:
96Test only changes:
57
97
58−- Allow QuickCheck 2.6.*
98+- Allow `QuickCheck` 2.6.*
59
99
601.2.11
1001.2.11
61
101
62−- Allow binary 0.7.*
102+- Allow `binary` 0.7.*
63
103
641.2.10
1041.2.10
65
105
66−- Allow cryptohash version 0.9.*
106+- Allow `cryptohash` version 0.9.*
67- Cleanup tests
107- Cleanup tests
68
108
691.2.9
1091.2.9
70
110
71−- Bumped dependency on 'cryptohash'.
111+- Bumped dependency on `cryptohash`.
72
112
731.2.8
1131.2.8
74
114
@@ -76,13 +116,13 @@ Test only changes:
76
116
771.2.7
1171.2.7
78
118
79−- Added stricter constraints on 'random' package.
119+- Added stricter constraints on `random` package.
80
120
811.2.6
1211.2.6
82
122
83−- Add module 'V4' to direct attention to our Random instance
123+- Add module `V4` to direct attention to our Random instance
84
124
85−- In module 'V1' seed the generator with a random number
125+- In module `V1` seed the generator with a random number
86 if the hardware MAC address could not be discovered.
126 if the hardware MAC address could not be discovered.
87
127
88- Fix and cleanup various haddocks.
128- Fix and cleanup various haddocks.
@@ -92,7 +132,7 @@ Test only changes:
92
132
931.2.5
1331.2.5
94
134
95−- Use 'cryptohash' package for MD5 and SHA1 instead of 'Crypto'
135+- Use `cryptohash` package for MD5 and SHA1 instead of `Crypto`
96
136
971.2.4
1371.2.4
98
138
@@ -125,7 +165,7 @@ and a test case)
125 (Contributors: Antoine Latter & Mark Lentczner)
165 (Contributors: Antoine Latter & Mark Lentczner)
126
166
127- added functions toByteString and fromByteString
167- added functions toByteString and fromByteString
128−- added 'nil' UUID
168+- added `nil` UUID
129- added unit tests and benchmarks, built when configured -ftest
169- added unit tests and benchmarks, built when configured -ftest
130- major speed up of to/from functions (as well as in general)
170- major speed up of to/from functions (as well as in general)
131- added version-3 generation (deterministic based on MD5)
171- added version-3 generation (deterministic based on MD5)
@@ -141,6 +181,6 @@ and a test case)
141
181
1421.1.1
1821.1.1
143
183
144−- no longer exporting 'null' from the prelude
184+- no longer exporting `null` from the prelude
145−- add 'null' predicate on UUIDs
185+- add `null` predicate on UUIDs
146- documentation fix (thanks Mark Lentczner)
186- documentation fix (thanks Mark Lentczner)
uuid/CONTRIBUTORSdeleted−13
@@ -1,13 +0,0 @@
1−In order of appearance:
2−
3−Antoine Latter
4−Jason Dusek
5−Tim Newsham
6−Mark Lentczner
7−Neil Mitchell
8−Bas van Dijk
9−Sergei Trofimovich
10−davean
11−Francesco Mazzoli
12−Michael Snoyman
13−Bardur Arantsson
uuid/Data/UUID/V1.hsdeleted−135
@@ -1,135 +0,0 @@
1−{-# OPTIONS_GHC -fno-cse #-}
2−{-# LANGUAGE TypeFamilies #-}
3−
4−{- |
5−Module : Data.UUID.V1
6−Copyright : (c) 2008 Jason Dusek
7− (c) 2009 Mark Lentczner
8− (c) 2009-2010,2012 Antoine Latter
9−
10−License : BSD-style
11−
12−Maintainer : aslatter@gmail.com
13−Stability : experimental
14−Portability : portable
15−
16−RFC 4122 Version 1 UUID state machine.
17−
18−The generated UUID is based on the hardware MAC
19−address and the system clock.
20−
21−If we cannot lookup the MAC address we seed the
22−generator with a psuedo-random number.
23−-}
24−
25−module Data.UUID.V1(nextUUID)
26−where
27−
28−
29−import Data.Bits
30−import Data.Maybe
31−import Data.Time
32−import Data.Word
33−
34−import Control.Applicative ((<$>),(<*>))
35−import Control.Concurrent.MVar
36−import System.IO.Unsafe
37−
38−import qualified System.Random as R
39−
40−import Network.Info
41−
42−import Data.UUID.Types.Internal.Builder
43−import Data.UUID.Types.Internal
44−
45−-- | Returns a new UUID derived from the local hardware MAC
46−-- address and the current system time.
47−-- Is generated according to the Version 1 UUID sepcified in
48−-- RFC 4122.
49−--
50−-- Returns 'Nothing' if you request UUIDs too quickly.
51−nextUUID :: IO (Maybe UUID)
52−nextUUID = do
53− res <- stepTime
54− case res of
55− Just (mac', c, t) -> return $ Just $ makeUUID t c mac'
56− _ -> return Nothing
57−
58−
59−makeUUID :: Word64 -> Word16 -> MAC -> UUID
60−makeUUID time clock mac' =
61− buildFromBytes 1 /-/ tLow /-/ tMid /-/ tHigh /-/ clock /-/ (MACSource mac')
62− where tLow = (fromIntegral time) :: Word32
63− tMid = (fromIntegral (time `shiftR` 32)) :: Word16
64− tHigh = (fromIntegral (time `shiftR` 48)) :: Word16
65−
66−newtype MACSource = MACSource MAC
67−instance ByteSource MACSource where
68− z /-/ (MACSource (MAC a b c d e f)) = z a b c d e f
69−type instance ByteSink MACSource g = Takes3Bytes (Takes3Bytes g)
70−
71−
72−-- |Approximates the clock algorithm in RFC 4122, section 4.2
73−-- Isn't system wide or thread safe, nor does it properly randomize
74−-- the clock value on initialization.
75−stepTime :: IO (Maybe (MAC, Word16, Word64))
76−stepTime = do
77− h1 <- fmap hundredsOfNanosSinceGregorianReform getCurrentTime
78− modifyMVar state $ \s@(State mac' c0 h0) ->
79− if h1 > h0
80− then
81− return (State mac' c0 h1, Just (mac', c0, h1))
82− else
83− let
84− c1 = succ c0
85− in if c1 <= 0x3fff -- when clock is initially randomized,
86− -- then this test will need to change
87− then
88− return (State mac' c1 h1, Just (mac', c1, h1))
89− else
90− return (s, Nothing)
91−
92−
93−{-# NOINLINE state #-}
94−state :: MVar State
95−state = unsafePerformIO $ do
96− h0 <- fmap hundredsOfNanosSinceGregorianReform getCurrentTime
97− mac' <- getMac
98− newMVar $ State mac' 0 h0 -- the 0 should be a random number
99−
100−-- SysMAC.mac can fail on some machines.
101−-- In those cases we fake it with a random
102−-- 6 bytes seed.
103−getMac :: IO MAC
104−getMac =
105− getNetworkInterfaces >>=
106− return . listToMaybe . filter (minBound /=) . map mac >>=
107− \macM -> case macM of
108− Just m -> return m
109− Nothing -> randomMac
110−
111−randomMac :: IO MAC
112−randomMac =
113− -- I'm too lazy to thread through
114− -- the random state ...
115− MAC
116− <$> (R.randomIO >>= return . (1 .|.)) -- We must set the multicast bit to True. See section 4.5 of the RFC.
117− <*> R.randomIO
118− <*> R.randomIO
119− <*> R.randomIO
120− <*> R.randomIO
121− <*> R.randomIO
122−
123−data State = State
124− {-# UNPACK #-} !MAC
125− {-# UNPACK #-} !Word16
126− {-# UNPACK #-} !Word64
127− deriving (Show)
128−
129−
130−
131−hundredsOfNanosSinceGregorianReform :: UTCTime -> Word64
132−hundredsOfNanosSinceGregorianReform t = floor $ 10000000 * dt
133− where
134− gregorianReform = UTCTime (fromGregorian 1582 10 15) 0
135− dt = t `diffUTCTime` gregorianReform
uuid/Data/UUID/V4.hsdeleted−28
@@ -1,28 +0,0 @@
1−{- |
2− Module : Data.UUID.V4
3− Copyright : (c) 2012 Antoine Latter
4−
5− License : BSD-style
6−
7− Maintainer : aslatter@gmail.com
8− Stability : experimental
9− Portability : portable
10−
11− This module implements Version 4 UUIDs as specified
12− in RFC 4122.
13−
14− These UUIDs are generated from a psuedo-random generator.
15− We use the System.Random 'R.StdGen' as our random source.
16−
17− All of the logic is encapsulated in the 'R.Random' instance
18− for the UUID type, so you are also free to use the random generator
19− of your choice.
20−-}
21−module Data.UUID.V4 (nextRandom) where
22−
23−import Data.UUID
24−import qualified System.Random as R
25−
26−-- | Generate a random UUID. Introduced in version 1.2.6.
27−nextRandom :: IO UUID
28−nextRandom = R.randomIO
uuid/Data/UUID.hs → uuid/src/Data/UUID.hsrenamed+7−5
@@ -14,11 +14,9 @@ printing Universally Unique Identifiers.
14See <http://en.wikipedia.org/wiki/UUID> for the general idea.
14See <http://en.wikipedia.org/wiki/UUID> for the general idea.
15See <http://tools.ietf.org/html/rfc4122> for the specification.
15See <http://tools.ietf.org/html/rfc4122> for the specification.
16
16
17−* Random UUIDs may be generated using 'Data.UUID.V4.nextRandom' or
17+* Use 'Data.UUID.V4.nextRandom' to generate secure random UUIDs, and your
18−your favorite instance of 'System.Random.Random'.
18+favorite instance of 'System.Random.Random' for faster but insecure
19−
19+generation of UUIDs.
20−* We have an implementation of generating a UUID from the hardware
21−MAC address and current system time in "Data.UUID.V1".
22
20
23* For name-based generation of UUIDs using SHA-1 hashing see
21* For name-based generation of UUIDs using SHA-1 hashing see
24"Data.UUID.V5".
22"Data.UUID.V5".
@@ -26,6 +24,8 @@ MAC address and current system time in "Data.UUID.V1".
26module Data.UUID(UUID
24module Data.UUID(UUID
27 ,toString
25 ,toString
28 ,fromString
26 ,fromString
27+ ,toText
28+ ,fromText
29 ,toASCIIBytes
29 ,toASCIIBytes
30 ,fromASCIIBytes
30 ,fromASCIIBytes
31 ,toLazyASCIIBytes
31 ,toLazyASCIIBytes
@@ -34,6 +34,8 @@ module Data.UUID(UUID
34 ,fromByteString
34 ,fromByteString
35 ,toWords
35 ,toWords
36 ,fromWords
36 ,fromWords
37+ ,toWords64
38+ ,fromWords64
37 ,null
39 ,null
38 ,nil
40 ,nil
39 ) where
41 ) where
uuid/Data/UUID/Named.hs → uuid/src/Data/UUID/Named.hsrenamed

The content is the same.

uuid/Data/UUID/Util.hs → uuid/src/Data/UUID/Util.hsrenamed−11
@@ -3,7 +3,6 @@ module Data.UUID.Util (
3 UnpackedUUID(..)
3 UnpackedUUID(..)
4 , unpack, pack
4 , unpack, pack
5 , version
5 , version
6− , extractMac
7 , extractTime
6 , extractTime
8 , setTime
7 , setTime
9 ) where
8 ) where
@@ -13,7 +12,6 @@ import Data.Word
13import Data.Word.Util
12import Data.Word.Util
14import Data.Bits
13import Data.Bits
15import Data.UUID.Types.Internal
14import Data.UUID.Types.Internal
16−import Network.Info
17import Data.Int (Int64)
15import Data.Int (Int64)
18
16
19version :: UUID -> Int
17version :: UUID -> Int
@@ -42,12 +40,3 @@ extractTime uuid =
42
40
43timeAndVersionToTime :: Word16 -> Word16
41timeAndVersionToTime :: Word16 -> Word16
44timeAndVersionToTime tv = tv .&. 0x0FFF
42timeAndVersionToTime tv = tv .&. 0x0FFF
45−
46−extractMac :: UUID -> Maybe MAC
47−extractMac uuid =
48− if version uuid == 1
49− then Just $
50− MAC (node_0 unpacked) (node_1 unpacked) (node_2 unpacked) (node_3 unpacked) (node_4 unpacked) (node_5 unpacked)
51− else Nothing
52− where
53− unpacked = unpack uuid
uuid/Data/UUID/V3.hs → uuid/src/Data/UUID/V3.hsrenamed+1−1
@@ -8,7 +8,7 @@ Maintainer : aslatter@gmail.com
8Stability : experimental
8Stability : experimental
9Portability : portable
9Portability : portable
10
10
11−NOTE: This module uses MD5 hashing. Unless you know
11+NOTE\: This module uses MD5 hashing. Unless you know
12you need to use this module, you should probably be
12you need to use this module, you should probably be
13using "Data.UUID.V5", which offers the same sort of
13using "Data.UUID.V5", which offers the same sort of
14functionality as this module except implemented with
14functionality as this module except implemented with
uuid/src/Data/UUID/V4.hsnew file+33
@@ -0,0 +1,33 @@
1+{- |
2+ Module : Data.UUID.V4
3+ Copyright : (c) 2012-2016 Antoine Latter
4+
5+ License : BSD-style
6+
7+ Maintainer : aslatter@gmail.com
8+ Stability : experimental
9+ Portability : portable
10+
11+ This module implements Version 4 UUIDs as specified
12+ in RFC 4122.
13+
14+ These UUIDs are generated from a pseudo-random generator.
15+ We use the 'getEntropy' method from the <https://hackage.haskell.org/package/entropy entropy> package,
16+ which should provide cryptographically secure random data.
17+-}
18+module Data.UUID.V4 (nextRandom) where
19+
20+import Data.UUID
21+import Data.UUID.Types.Internal ( buildFromBytes )
22+
23+import System.Entropy ( getEntropy )
24+import Data.ByteString ( unpack )
25+
26+-- | Generate a crytographically secure, random UUID.
27+--
28+-- @since 1.2.6
29+nextRandom :: IO UUID
30+nextRandom = do
31+ [b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, ba, bb, bc, bd, be, bf]
32+ <- unpack `fmap` getEntropy 16
33+ return $ buildFromBytes 4 b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf
uuid/Data/UUID/V5.hs → uuid/src/Data/UUID/V5.hsrenamed

The content is the same.

uuid/Data/Word/Util.hs → uuid/src/Data/Word/Util.hsrenamed

The content is the same.

uuid/tests/TestUUID.hs+30−41
@@ -1,63 +1,53 @@
1{-# LANGUAGE ViewPatterns #-}
1{-# LANGUAGE ViewPatterns #-}
2−import Control.Monad (replicateM)
2+
3import Data.Bits
3import Data.Bits
4import qualified Data.ByteString.Lazy as BL
4import qualified Data.ByteString.Lazy as BL
5import Data.Char (ord)
5import Data.Char (ord)
6−import Data.List (nub, (\\))
7import Data.Maybe
6import Data.Maybe
8import Data.Word
7import Data.Word
9import qualified Data.UUID as U
8import qualified Data.UUID as U
10−import qualified Data.UUID.V1 as U
11import qualified Data.UUID.V3 as U3
9import qualified Data.UUID.V3 as U3
12import qualified Data.UUID.V5 as U5
10import qualified Data.UUID.V5 as U5
13−import qualified Test.HUnit as H
14−import Test.HUnit hiding (Test)
15−import Test.QuickCheck hiding ((.&.))
16−import Test.Framework (defaultMain, Test)
17−import Test.Framework.Providers.HUnit (hUnitTestToTests)
18−import Test.Framework.Providers.QuickCheck2 (testProperty)
19
11
12+import Test.QuickCheck ( Arbitrary(arbitrary) )
13+import Test.Tasty ( TestTree, testGroup, defaultMain )
14+import Test.Tasty.HUnit
15+ ( assertBool, (@?=), testCase )
16+import Test.Tasty.QuickCheck ( testProperty )
17+
18+type Test = TestTree
20
19
21isValidVersion :: Int -> U.UUID -> Bool
20isValidVersion :: Int -> U.UUID -> Bool
22isValidVersion v u = lenOK && variantOK && versionOK
21isValidVersion v u = lenOK && variantOK && versionOK
23 where bs = U.toByteString u
22 where bs = U.toByteString u
24 lenOK = BL.length bs == 16
23 lenOK = BL.length bs == 16
25− variantOK = (BL.index bs 8) .&. 0xc0 == 0x80
24+ variantOK = BL.index bs 8 .&. 0xc0 == 0x80
26− versionOK = (BL.index bs 6) .&. 0xf0 == fromIntegral (v `shiftL` 4)
25+ versionOK = BL.index bs 6 .&. 0xf0 == fromIntegral (v `shiftL` 4)
27
26
28
27
29instance Arbitrary U.UUID where
28instance Arbitrary U.UUID where
30 -- the UUID random instance ignores bounds
29 -- the UUID random instance ignores bounds
31− arbitrary = choose (U.nil, U.nil)
30+ arbitrary = pure U.nil
32−
31+
33−
32+
34−test_null :: H.Test
33+test_null :: Test
35−test_null = H.TestList [
34+test_null =
35+ testCase "namespaceDNS is not null" $
36− "namespaceDNS is not null" ~: assertBool "" (not $ U.null U3.namespaceDNS)
36+ assertBool "" (not $ U.null U3.namespaceDNS)
37− ]
37+
38−
39−test_v1 :: [Maybe U.UUID] -> H.Test
40−test_v1 v1s = H.TestList [
41− "V1 unique" ~: nub (v1s \\ nub v1s) @?= [],
42− "V1 not null" ~: H.TestList $ map (testUUID (not . U.null)) v1s,
43− "V1 valid" ~: H.TestList $ map (testUUID (isValidVersion 1)) v1s
44− ]
45− where testUUID :: (U.UUID -> Bool) -> Maybe U.UUID -> H.Test
46− testUUID p u = maybe False p u ~? show u
47−
48−test_v3 :: H.Test
38+test_v3 :: Test
49−test_v3 = H.TestList [
39+test_v3 =
50− "V3 computation" ~:
40+ testCase "V3 computation" $
51 U3.generateNamed U3.namespaceDNS name @?= uV3
41 U3.generateNamed U3.namespaceDNS name @?= uV3
52− ]
53− where name = map (fromIntegral . ord) "www.widgets.com" :: [Word8]
54− uV3 = fromJust $ U.fromString "3d813cbb-47fb-32ba-91df-831e1593ac29"
55
42
56−test_v5 :: H.Test
43+ where name = map (fromIntegral . ord) "www.widgets.com" :: [Word8]
44+ uV3 = fromJust $ U.fromString "3d813cbb-47fb-32ba-91df-831e1593ac29"
45+
46+test_v5 :: Test
57−test_v5 = H.TestList [
47+test_v5 =
58− "V5 computation" ~:
48+ testCase "V5 computation" $
59 U5.generateNamed U5.namespaceDNS name @?= uV5
49 U5.generateNamed U5.namespaceDNS name @?= uV5
60− ]
50+
61 where name = map (fromIntegral . ord) "www.widgets.com" :: [Word8]
51 where name = map (fromIntegral . ord) "www.widgets.com" :: [Word8]
62 uV5 = fromJust $ U.fromString "21f7f8de-8051-5b89-8680-0195ef798b6a"
52 uV5 = fromJust $ U.fromString "21f7f8de-8051-5b89-8680-0195ef798b6a"
63
53
@@ -89,12 +79,11 @@ prop_v5Valid = testProperty "V5 valid" v5Valid
89
79
90main :: IO ()
80main :: IO ()
91main = do
81main = do
92− v1s <- replicateM 100 U.nextUUID
93 defaultMain $
82 defaultMain $
83+ testGroup "tests" $
94 concat $
84 concat $
95− [ hUnitTestToTests $ H.TestList [
85+ [ [
96 test_null,
86 test_null,
97− test_v1 v1s,
98 test_v3,
87 test_v3,
99 test_v5
88 test_v5
100 ]
89 ]
uuid/tests/summarize-bench-results.pldeleted−14
@@ -1,14 +0,0 @@
1−#!/usr/bin/env perl
2−
3−
4−while(<>) {
5− if (/^benchmarking (.*)$/) {
6− $name = $1;
7− }
8− if (/^mean:\s*([\d.]*) (\w*),/) {
9− $mean = 1 * $1;
10− $units = $2;
11−
12− printf "%-30s %10.2f %2s\n", $name, $mean, $units;
13− }
14−}
uuid/uuid.cabal+84−72
@@ -1,83 +1,95 @@
1+cabal-version: 1.12
1−Name: uuid
2+name: uuid
2−Version: 1.3.9
3+version: 1.3.16
4+x-revision: 2
3−Copyright: (c) 2008-2014 Antoine Latter
5+copyright: (c) 2008-2014 Antoine Latter
4−Author: Antoine Latter
6+author: Antoine Latter
5−Maintainer: aslatter@gmail.com
7+maintainer: Oleg Grenrus <oleg.grenrus@iki.fi>
6−License: BSD3
8+license: BSD3
7−License-file: LICENSE
9+license-file: LICENSE
10+category: Data
11+build-type: Simple
12+tested-with:
13+ GHC ==8.6.5
14+ || ==8.8.4
15+ || ==8.10.7
16+ || ==9.0.2
17+ || ==9.2.8
18+ || ==9.4.8
19+ || ==9.6.6
20+ || ==9.8.4
21+ || ==9.10.1
22+ || ==9.12.1
8
23
9−Category: Data
24+synopsis:
10−Build-Type: Simple
25+ For creating, comparing, parsing and printing Universally Unique Identifiers
11−Cabal-Version: >= 1.8
12
26
13−Description:
27+description:
14− This library is useful for creating, comparing, parsing and
28+ This library is useful for creating, comparing, parsing and
15− printing Universally Unique Identifiers.
29+ printing Universally Unique Identifiers.
30+ .
16− See <http://en.wikipedia.org/wiki/UUID> for the general idea.
31+ See <http://en.wikipedia.org/wiki/UUID> for the general idea.
17
32
18−Synopsis: For creating, comparing, parsing and printing Universally Unique Identifiers
33+homepage: https://github.com/haskell-hvr/uuid
34+bug-reports: https://github.com/haskell-hvr/uuid/issues
35+extra-source-files: CHANGES.md
19
36
37+source-repository head
38+ type: git
20−Homepage: https://github.com/aslatter/uuid
39+ location: https://github.com/haskell-hvr/uuid.git
21−Bug-Reports: https://github.com/aslatter/uuid/issues
40+ subdir: uuid
22
41
23−Extra-Source-Files:
42+library
24− CHANGES
43+ build-depends:
25− CONTRIBUTORS
44+ base >=4.12 && <5
45+ , binary >=0.8.6.0 && <0.9
46+ , bytestring >=0.10.8.2 && <0.13
47+ , cryptohash-md5 >=0.11.100 && <0.12
48+ , cryptohash-sha1 >=0.11.100 && <0.12
49+ , entropy >=0.3.7 && <0.5
26
50
51+ -- strict dependency on uuid-types,
52+ -- as we re-rexport datatype, thus leak instances etc.
53+ build-depends: uuid-types >=1.0.6 && <1.0.7
54+ exposed-modules:
55+ Data.UUID
56+ Data.UUID.Util
57+ Data.UUID.V3
58+ Data.UUID.V4
59+ Data.UUID.V5
27
60
28−Library
61+ other-modules:
29− Build-Depends: base >=3 && < 5,
62+ Data.UUID.Named
30− binary >= 0.4 && < 0.8,
63+ Data.Word.Util
31− bytestring >= 0.9 && < 1.1,
32− cryptohash >= 0.7 && < 0.12,
33− network-info == 0.2.*,
34− random >= 1.0.1 && < 1.2,
35− time >= 1.1 && < 1.6,
36− uuid-types >= 1.0 && < 2
37
64
38− Exposed-Modules:
65+ default-language: Haskell2010
39− Data.UUID
66+ default-extensions: DeriveDataTypeable
40− Data.UUID.Util
67+ other-extensions: TypeFamilies
41− Data.UUID.V1
68+ ghc-options: -Wall
42− Data.UUID.V3
69+ if impl(ghc >= 8.10)
43− Data.UUID.V4
70+ ghc-options: -Wunused-packages
44− Data.UUID.V5
71+ hs-source-dirs: src
45
72
46− Other-Modules:
73+test-suite testuuid
47− Data.UUID.Named
74+ type: exitcode-stdio-1.0
48− Data.Word.Util
75+ main-is: TestUUID.hs
76+ hs-source-dirs: tests
77+ default-language: Haskell2010
78+ default-extensions: DeriveDataTypeable
79+ other-extensions: ViewPatterns
80+ ghc-options: -Wall -fno-warn-orphans
81+ if impl(ghc >= 8.10)
82+ ghc-options: -Wunused-packages
49
83
50− Extensions: DeriveDataTypeable
84+ -- inherited constraints
51− Ghc-Options: -Wall
85+ build-depends:
86+ base
87+ , bytestring
88+ , uuid
52
89
53−source-repository head
90+ -- deps w/o inherited constraints
54− type: git
91+ build-depends:
55− location: https://github.com/aslatter/uuid.git
92+ QuickCheck >=2.14.2 && <2.16
56−
93+ , tasty >=1.4.0.1 && <1.6
57−Test-Suite testuuid
94+ , tasty-hunit >=0.10 && <0.11
58− Type: exitcode-stdio-1.0
95+ , tasty-quickcheck >=0.10 && <0.12
59− Main-is: TestUUID.hs
60− Hs-source-dirs: tests
61− Extensions: DeriveDataTypeable
62− Ghc-Options: -Wall -fno-warn-orphans
63− Build-Depends: base >= 3 && < 5,
64− uuid,
65− bytestring >= 0.9 && < 1.1,
66− HUnit >=1.2 && < 1.3,
67− QuickCheck >=2.4 && < 2.8,
68− random >= 1.0.1 && < 1.2,
69− test-framework == 0.8.*,
70− test-framework-hunit == 0.3.*,
71− test-framework-quickcheck2 == 0.3.*
72−
73−benchmark benchmark
74− Type: exitcode-stdio-1.0
75− Main-is: BenchUUID.hs
76− Hs-source-dirs: tests
77− Extensions: DeriveDataTypeable, CPP
78− Ghc-Options: -Wall -fno-warn-orphans
79− Build-depends: base == 4.*,
80− uuid,
81− criterion >= 0.4 && < 0.9,
82− mersenne-random-pure64,
83− random >= 1.0.1 && < 1.2