-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathsorted-map-builder.rkt
87 lines (63 loc) · 2.86 KB
/
sorted-map-builder.rkt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#lang racket/base
(require racket/contract/base)
(provide
(contract-out
[sorted-map-builder? (-> any/c boolean?)]
[sorted-map-builder-put (-> sorted-map-builder? any/c any/c sorted-map-builder?)]
[sorted-map-builder-put-all (-> sorted-map-builder? (sequence/c entry?) sorted-map-builder?)]
[make-sorted-map-builder (-> comparator? sorted-map-builder?)]
[build-sorted-map (-> sorted-map-builder? immutable-sorted-map?)]))
(require racket/match
racket/sequence
racket/unsafe/ops
racket/vector
rebellion/base/comparator
rebellion/collection/entry
rebellion/collection/vector
rebellion/collection/vector/builder
(submod rebellion/collection/private/persistent-sorted-map private-for-rebellion-only)
(submod rebellion/collection/private/regular-immutable-sorted-map private-for-rebellion-only)
rebellion/collection/private/sorted-map-interface
rebellion/streaming/transducer
guard
rebellion/private/static-name)
;@----------------------------------------------------------------------------------------------------
(struct sorted-map-builder
(key-comparator entry-vector-builder)
#:omit-define-syntaxes
#:constructor-name constructor:sorted-map-builder)
(define (make-sorted-map-builder key-comparator)
(constructor:sorted-map-builder key-comparator (make-vector-builder)))
(define (sorted-map-builder-put builder key value)
(vector-builder-add (sorted-map-builder-entry-vector-builder builder) (entry key value))
builder)
(define (sorted-map-builder-put-all builder entries)
(vector-builder-add-all (sorted-map-builder-entry-vector-builder builder) entries)
builder)
(define/guard (build-sorted-map builder)
(define key<=> (sorted-map-builder-key-comparator builder))
(define mutable-entries (build-mutable-vector (sorted-map-builder-entry-vector-builder builder)))
(guard (not (vector-empty? mutable-entries)) #:else
(empty-sorted-map key<=>))
(define (entry< e1 e2)
(compare-infix key<=> (entry-key e1) < (entry-key e2)))
(vector-sort! mutable-entries entry<)
(define value-vector (make-vector (vector-length mutable-entries)))
(for/fold ([previous #false] #:result (void))
([i (in-range (vector-length mutable-entries))])
(define e (vector-ref mutable-entries i))
(match-define (entry key value) e)
(when (and previous (compare-infix key<=> (entry-key previous) == key))
(raise-arguments-error
(name build-sorted-map)
"multiple values for the same key are not allowed"
"key" key
"value1" (entry-value previous)
"value2" value))
(vector-set! mutable-entries i key)
(vector-set! value-vector i value)
e)
(constructor:regular-immutable-sorted-map
(unsafe-vector*->immutable-vector! mutable-entries)
(unsafe-vector*->immutable-vector! value-vector)
key<=>))