@fncts/schema 0.0.16 → 0.0.17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (151) hide show
  1. package/AST.d.ts +19 -6
  2. package/ASTAnnotation.d.ts +10 -2
  3. package/ParseError/ParseError.d.ts +231 -0
  4. package/ParseError/ParseErrorFormatter.d.ts +2 -0
  5. package/ParseError/PathFormatter.d.ts +13 -0
  6. package/ParseError/TreeFormatter.d.ts +14 -0
  7. package/ParseError.d.ts +4 -144
  8. package/ParseResult.d.ts +1 -8
  9. package/Parser/interpreter.d.ts +0 -1
  10. package/Schema/api/conc.d.ts +0 -2
  11. package/Schema/api/hashMap.d.ts +0 -1
  12. package/Schema/api/hashSet.d.ts +0 -1
  13. package/Schema/api/immutableArray.d.ts +0 -1
  14. package/Schema/api/list.d.ts +1 -2
  15. package/Schema/api/map.d.ts +19 -0
  16. package/Schema/api/set.d.ts +19 -0
  17. package/Schema/api.d.ts +11 -1
  18. package/Schema.d.ts +2 -0
  19. package/Show.d.ts +7 -3
  20. package/_cjs/AST.cjs +180 -113
  21. package/_cjs/AST.cjs.map +1 -1
  22. package/_cjs/ASTAnnotation.cjs +6 -1
  23. package/_cjs/ASTAnnotation.cjs.map +1 -1
  24. package/_cjs/Gen.cjs +24 -24
  25. package/_cjs/Gen.cjs.map +1 -1
  26. package/_cjs/ParseError/ParseError.cjs +260 -0
  27. package/_cjs/ParseError/ParseError.cjs.map +1 -0
  28. package/_cjs/ParseError/ParseErrorFormatter.cjs +6 -0
  29. package/_cjs/ParseError/ParseErrorFormatter.cjs.map +1 -0
  30. package/_cjs/ParseError/PathFormatter.cjs +94 -0
  31. package/_cjs/ParseError/PathFormatter.cjs.map +1 -0
  32. package/_cjs/ParseError/TreeFormatter.cjs +123 -0
  33. package/_cjs/ParseError/TreeFormatter.cjs.map +1 -0
  34. package/_cjs/ParseError.cjs +43 -289
  35. package/_cjs/ParseError.cjs.map +1 -1
  36. package/_cjs/ParseResult.cjs +1 -10
  37. package/_cjs/ParseResult.cjs.map +1 -1
  38. package/_cjs/Parser/api.cjs +2 -2
  39. package/_cjs/Parser/api.cjs.map +1 -1
  40. package/_cjs/Parser/definition.cjs +1 -1
  41. package/_cjs/Parser/interpreter.cjs +121 -117
  42. package/_cjs/Parser/interpreter.cjs.map +1 -1
  43. package/_cjs/Schema/api/conc.cjs +35 -45
  44. package/_cjs/Schema/api/conc.cjs.map +1 -1
  45. package/_cjs/Schema/api/either.cjs +24 -30
  46. package/_cjs/Schema/api/either.cjs.map +1 -1
  47. package/_cjs/Schema/api/hashMap.cjs +41 -101
  48. package/_cjs/Schema/api/hashMap.cjs.map +1 -1
  49. package/_cjs/Schema/api/hashSet.cjs +46 -106
  50. package/_cjs/Schema/api/hashSet.cjs.map +1 -1
  51. package/_cjs/Schema/api/immutableArray.cjs +22 -48
  52. package/_cjs/Schema/api/immutableArray.cjs.map +1 -1
  53. package/_cjs/Schema/api/list.cjs +35 -52
  54. package/_cjs/Schema/api/list.cjs.map +1 -1
  55. package/_cjs/Schema/api/map.cjs +97 -0
  56. package/_cjs/Schema/api/map.cjs.map +1 -0
  57. package/_cjs/Schema/api/maybe.cjs +24 -35
  58. package/_cjs/Schema/api/maybe.cjs.map +1 -1
  59. package/_cjs/Schema/api/set.cjs +76 -0
  60. package/_cjs/Schema/api/set.cjs.map +1 -0
  61. package/_cjs/Schema/api.cjs +20 -2
  62. package/_cjs/Schema/api.cjs.map +1 -1
  63. package/_cjs/Schema.cjs +22 -0
  64. package/_cjs/Schema.cjs.map +1 -1
  65. package/_cjs/Show.cjs +106 -89
  66. package/_cjs/Show.cjs.map +1 -1
  67. package/_cjs/utils.cjs +5 -0
  68. package/_cjs/utils.cjs.map +1 -1
  69. package/_mjs/AST.mjs +177 -112
  70. package/_mjs/AST.mjs.map +1 -1
  71. package/_mjs/ASTAnnotation.mjs +5 -0
  72. package/_mjs/ASTAnnotation.mjs.map +1 -1
  73. package/_mjs/Gen.mjs +24 -24
  74. package/_mjs/Gen.mjs.map +1 -1
  75. package/_mjs/ParseError/ParseError.mjs +228 -0
  76. package/_mjs/ParseError/ParseError.mjs.map +1 -0
  77. package/_mjs/ParseError/ParseErrorFormatter.mjs +2 -0
  78. package/_mjs/ParseError/ParseErrorFormatter.mjs.map +1 -0
  79. package/_mjs/ParseError/PathFormatter.mjs +86 -0
  80. package/_mjs/ParseError/PathFormatter.mjs.map +1 -0
  81. package/_mjs/ParseError/TreeFormatter.mjs +113 -0
  82. package/_mjs/ParseError/TreeFormatter.mjs.map +1 -0
  83. package/_mjs/ParseError.mjs +6 -270
  84. package/_mjs/ParseError.mjs.map +1 -1
  85. package/_mjs/ParseResult.mjs +1 -9
  86. package/_mjs/ParseResult.mjs.map +1 -1
  87. package/_mjs/Parser/api.mjs +2 -2
  88. package/_mjs/Parser/api.mjs.map +1 -1
  89. package/_mjs/Parser/definition.mjs +1 -1
  90. package/_mjs/Parser/interpreter.mjs +121 -117
  91. package/_mjs/Parser/interpreter.mjs.map +1 -1
  92. package/_mjs/Schema/api/conc.mjs +35 -44
  93. package/_mjs/Schema/api/conc.mjs.map +1 -1
  94. package/_mjs/Schema/api/either.mjs +24 -30
  95. package/_mjs/Schema/api/either.mjs.map +1 -1
  96. package/_mjs/Schema/api/hashMap.mjs +41 -101
  97. package/_mjs/Schema/api/hashMap.mjs.map +1 -1
  98. package/_mjs/Schema/api/hashSet.mjs +46 -106
  99. package/_mjs/Schema/api/hashSet.mjs.map +1 -1
  100. package/_mjs/Schema/api/immutableArray.mjs +23 -49
  101. package/_mjs/Schema/api/immutableArray.mjs.map +1 -1
  102. package/_mjs/Schema/api/list.mjs +35 -52
  103. package/_mjs/Schema/api/list.mjs.map +1 -1
  104. package/_mjs/Schema/api/map.mjs +88 -0
  105. package/_mjs/Schema/api/map.mjs.map +1 -0
  106. package/_mjs/Schema/api/maybe.mjs +24 -35
  107. package/_mjs/Schema/api/maybe.mjs.map +1 -1
  108. package/_mjs/Schema/api/set.mjs +67 -0
  109. package/_mjs/Schema/api/set.mjs.map +1 -0
  110. package/_mjs/Schema/api.mjs +18 -2
  111. package/_mjs/Schema/api.mjs.map +1 -1
  112. package/_mjs/Schema.mjs +2 -0
  113. package/_mjs/Schema.mjs.map +1 -1
  114. package/_mjs/Show.mjs +106 -90
  115. package/_mjs/Show.mjs.map +1 -1
  116. package/_mjs/utils.mjs +4 -0
  117. package/_mjs/utils.mjs.map +1 -1
  118. package/_src/AST.ts +144 -43
  119. package/_src/ASTAnnotation.ts +8 -1
  120. package/_src/Gen.ts +12 -9
  121. package/_src/ParseError/ParseError.ts +304 -0
  122. package/_src/ParseError/ParseErrorFormatter.ts +1 -0
  123. package/_src/ParseError/PathFormatter.ts +117 -0
  124. package/_src/ParseError/TreeFormatter.ts +127 -0
  125. package/_src/ParseError.ts +7 -331
  126. package/_src/ParseResult.ts +2 -9
  127. package/_src/Parser/api.ts +1 -1
  128. package/_src/Parser/interpreter.ts +98 -75
  129. package/_src/Schema/api/conc.ts +33 -42
  130. package/_src/Schema/api/either.ts +20 -30
  131. package/_src/Schema/api/hashMap.ts +40 -124
  132. package/_src/Schema/api/hashSet.ts +31 -117
  133. package/_src/Schema/api/immutableArray.ts +15 -45
  134. package/_src/Schema/api/list.ts +32 -55
  135. package/_src/Schema/api/map.ts +93 -0
  136. package/_src/Schema/api/maybe.ts +19 -34
  137. package/_src/Schema/api/set.ts +74 -0
  138. package/_src/Schema/api.ts +20 -2
  139. package/_src/Schema.ts +2 -0
  140. package/_src/Show.ts +156 -128
  141. package/_src/global.ts +0 -4
  142. package/_src/utils.ts +5 -0
  143. package/global.d.ts +0 -4
  144. package/package.json +2 -2
  145. package/utils.d.ts +1 -0
  146. package/ParseFailure.d.ts +0 -18
  147. package/_cjs/ParseFailure.cjs +0 -28
  148. package/_cjs/ParseFailure.cjs.map +0 -1
  149. package/_mjs/ParseFailure.mjs +0 -20
  150. package/_mjs/ParseFailure.mjs.map +0 -1
  151. package/_src/ParseFailure.ts +0 -18
@@ -1,28 +1,17 @@
1
- import type {
2
- ArrayNode,
3
- CollisionNode,
4
- EmptyNode,
5
- IndexedNode,
6
- LeafNode,
7
- Node,
8
- } from "@fncts/base/collection/immutable/HashMap/internal";
1
+ import type { KeyError } from "@fncts/schema/ParseError";
9
2
  import type { Sized } from "@fncts/test/control/Sized";
10
3
  import type { Check } from "@fncts/typelevel";
11
4
 
12
5
  import { HashMap } from "@fncts/base/collection/immutable/HashMap";
13
- import { HashMapTypeId, HashMapVariance } from "@fncts/base/collection/immutable/HashMap";
14
6
  import { ASTAnnotation } from "@fncts/schema/ASTAnnotation";
15
7
 
16
8
  /**
17
9
  * @tsplus static fncts.schema.SchemaOps hashMap
18
10
  */
19
11
  export function hashMap<K, V>(key: Schema<K>, value: Schema<V>): Schema<HashMap<K, V>> {
20
- return Schema.declaration(
21
- Vector(key, value),
22
- inline(key, value),
23
- hashMapParser,
24
- ASTAnnotationMap.empty.annotate(ASTAnnotation.Identifier, "HashMap").annotate(ASTAnnotation.GenHook, gen),
25
- );
12
+ return Schema.declaration(Vector(key, value), hashMapParser(true), hashMapParser(false))
13
+ .annotate(ASTAnnotation.Identifier, `HashMap<${key.show()}, ${value.show()}>`)
14
+ .annotate(ASTAnnotation.GenHook, gen);
26
15
  }
27
16
 
28
17
  /**
@@ -65,118 +54,45 @@ export function deriveHashMap<A extends HashMap<any, any>>(
65
54
  return unsafeCoerce(hashMapFromRecord(key as Schema<string | symbol>, value));
66
55
  }
67
56
 
68
- function hashMapParser<K, V>(key: Schema<K>, value: Schema<V>): Parser<HashMap<K, V>> {
69
- const schema = hashMap(key, value);
70
- return Parser.make((u, options) => {
71
- if (!HashMap.is(u)) {
72
- return ParseResult.fail(ParseError.TypeError(schema.ast, u));
73
- }
74
- const allErrors = options?.allErrors;
75
- const errors = Vector.emptyPushable<ParseError>();
76
- const out = HashMap.empty<K, V>().beginMutation;
77
- for (const [k, v] of u) {
78
- const tk = key.decode(k, options);
79
- Either.concrete(tk);
80
- if (tk.isLeft()) {
81
- errors.push(ParseError.KeyError(key.ast, k, tk.left.errors));
82
- if (!allErrors) {
83
- return ParseResult.failures(errors);
84
- }
57
+ function hashMapParser(isDecoding: boolean) {
58
+ return <K, V>(key: Schema<K>, value: Schema<V>): Parser<HashMap<unknown, unknown>> => {
59
+ const schema = hashMap(key, value);
60
+ return Parser.make((u, options) => {
61
+ if (!HashMap.is(u)) {
62
+ return ParseResult.fail(ParseError.TypeError(schema.ast, u));
85
63
  }
86
- const tv = value.decode(v, options);
87
- Either.concrete(tv);
88
- if (tv.isLeft()) {
89
- errors.push(ParseError.TypeError(value.ast, tv.left));
90
- if (!allErrors) {
91
- return ParseResult.failures(errors);
64
+ const allErrors = options?.allErrors;
65
+ const errors = Vector.emptyPushable<KeyError>();
66
+ const out = HashMap.empty<unknown, unknown>().beginMutation;
67
+ const keyParser = isDecoding ? key.decode : key.encode;
68
+ const valueParser = isDecoding ? value.decode : value.encode;
69
+ for (const [k, v] of u) {
70
+ const tk = keyParser(k, options);
71
+ Either.concrete(tk);
72
+ if (tk.isLeft()) {
73
+ errors.push(ParseError.KeyError(key.ast, k, tk.left));
74
+ if (!allErrors) {
75
+ return ParseResult.fail(ParseError.IterableError(schema.ast, u, errors));
76
+ }
92
77
  }
78
+ const tv = valueParser(v, options);
79
+ Either.concrete(tv);
80
+ if (tv.isLeft()) {
81
+ errors.push(ParseError.KeyError(key.ast, k, ParseError.TypeError(value.ast, tv.left)));
82
+ if (!allErrors) {
83
+ return ParseResult.fail(ParseError.IterableError(schema.ast, u, errors));
84
+ }
85
+ }
86
+ if (tk.isLeft() || tv.isLeft()) {
87
+ continue;
88
+ }
89
+ out.set(tk.right, tv.right);
93
90
  }
94
- if (tk.isLeft() || tv.isLeft()) {
95
- continue;
96
- }
97
- out.set(tk.right, tv.right);
98
- }
99
- return errors.isNonEmpty() ? ParseResult.failures(errors) : ParseResult.succeed(out.endMutation);
100
- });
101
- }
102
-
103
- function emptyNodeSchema<K, V>(_key: Schema<K>, _value: Schema<V>): Schema<EmptyNode<K, V>> {
104
- return Schema.struct({
105
- _tag: Schema.literal("EmptyNode"),
106
- modify: Schema.any,
107
- });
108
- }
109
-
110
- function leafNodeSchema<K, V>(key: Schema<K>, value: Schema<V>): Schema<LeafNode<K, V>> {
111
- return Schema.struct({
112
- _tag: Schema.literal("LeafNode"),
113
- edit: Schema.number,
114
- hash: Schema.number,
115
- key,
116
- value: value.maybe,
117
- modify: Schema.any,
118
- });
119
- }
120
-
121
- function collisionNodeSchema<K, V>(key: Schema<K>, value: Schema<V>): Schema<CollisionNode<K, V>> {
122
- return Schema.lazy(() =>
123
- Schema.struct({
124
- _tag: Schema.literal("CollisionNode"),
125
- edit: Schema.number,
126
- hash: Schema.number,
127
- children: nodeSchema(key, value).mutableArray,
128
- modify: Schema.any,
129
- }),
130
- );
131
- }
132
-
133
- function indexedNodeSchema<K, V>(key: Schema<K>, value: Schema<V>): Schema<IndexedNode<K, V>> {
134
- return Schema.lazy(() =>
135
- Schema.struct({
136
- _tag: Schema.literal("IndexedNode"),
137
- edit: Schema.number,
138
- mask: Schema.number,
139
- children: nodeSchema(key, value).mutableArray,
140
- modify: Schema.any,
141
- }),
142
- );
143
- }
144
-
145
- function arrayNodeSchema<K, V>(key: Schema<K>, value: Schema<V>): Schema<ArrayNode<K, V>> {
146
- return Schema.lazy(() =>
147
- Schema.struct({
148
- _tag: Schema.literal("ArrayNode"),
149
- edit: Schema.number,
150
- size: Schema.number,
151
- children: nodeSchema(key, value).mutableArray,
152
- modify: Schema.any,
153
- }),
154
- );
155
- }
156
-
157
- function nodeSchema<K, V>(key: Schema<K>, value: Schema<V>): Schema<Node<K, V>> {
158
- return Schema.union(
159
- emptyNodeSchema(key, value),
160
- leafNodeSchema(key, value),
161
- collisionNodeSchema(key, value),
162
- indexedNodeSchema(key, value),
163
- arrayNodeSchema(key, value),
164
- );
165
- }
166
-
167
- function inline<K, V>(key: Schema<K>, value: Schema<V>): Schema<HashMap<K, V>> {
168
- return Schema.struct({
169
- [HashMapTypeId]: Schema.uniqueSymbol(HashMapTypeId),
170
- [HashMapVariance]: Schema.any,
171
- editable: Schema.boolean,
172
- edit: Schema.number,
173
- config: Schema.any,
174
- root: nodeSchema(key, value),
175
- size: Schema.number,
176
- [Symbol.iterator]: Schema.any,
177
- [Symbol.hash]: Schema.any,
178
- [Symbol.equals]: Schema.any,
179
- });
91
+ return errors.isNonEmpty()
92
+ ? ParseResult.fail(ParseError.IterableError(schema.ast, u, errors))
93
+ : ParseResult.succeed(out.endMutation);
94
+ });
95
+ };
180
96
  }
181
97
 
182
98
  function gen<K, V>(key: Gen<Sized, K>, value: Gen<Sized, V>): Gen<Sized, HashMap<K, V>> {
@@ -1,25 +1,12 @@
1
+ import type { KeyError } from "@fncts/schema/ParseError";
1
2
  import type { Sized } from "@fncts/test/control/Sized";
2
3
 
3
- import {
4
- type ArrayNode,
5
- type CollisionNode,
6
- type EmptyNode,
7
- HashSetTypeId,
8
- HashSetVariance,
9
- type IndexedNode,
10
- type LeafNode,
11
- type Node,
12
- } from "@fncts/base/collection/immutable/HashSet/definition";
13
4
  import { ASTAnnotation } from "@fncts/schema/ASTAnnotation";
14
- import { ASTAnnotationMap } from "@fncts/schema/ASTAnnotationMap";
15
5
 
16
6
  export function hashSet<A>(value: Schema<A>): Schema<HashSet<A>> {
17
- return Schema.declaration(
18
- Vector(value),
19
- inline(value),
20
- hashSetParser,
21
- ASTAnnotationMap.empty.annotate(ASTAnnotation.Identifier, "HashMap").annotate(ASTAnnotation.GenHook, gen),
22
- );
7
+ return Schema.declaration(Vector(value), hashSetParser(true), hashSetParser(false))
8
+ .annotate(ASTAnnotation.Identifier, `HashSet<${value.show()}>`)
9
+ .annotate(ASTAnnotation.GenHook, gen);
23
10
  }
24
11
 
25
12
  /**
@@ -58,108 +45,35 @@ export function deriveHashSet<A extends HashSet<any>>(
58
45
  return unsafeCoerce(hashSetFromArray(value));
59
46
  }
60
47
 
61
- function hashSetParser<A>(value: Schema<A>): Parser<HashSet<A>> {
62
- const schema = hashSet(value);
63
- return Parser.make((u, options) => {
64
- if (!HashSet.is(u)) {
65
- return ParseResult.fail(ParseError.TypeError(schema.ast, u));
66
- }
67
- const allErrors = options?.allErrors;
68
- const errors = Vector.emptyPushable<ParseError>();
69
- const out = HashSet.empty<A>().beginMutation;
70
- for (const v of u) {
71
- const tv = value.decode(v, options);
72
- Either.concrete(tv);
73
- if (tv.isLeft()) {
74
- errors.push(ParseError.TypeError(value.ast, tv.left));
75
- if (!allErrors) {
76
- return ParseResult.failures(errors);
77
- }
78
- continue;
48
+ function hashSetParser(isDecoding: boolean) {
49
+ return <A>(value: Schema<A>): Parser<HashSet<unknown>> => {
50
+ const schema = hashSet(value);
51
+ const parseValue = isDecoding ? value.decode : value.encode;
52
+ return Parser.make((u, options) => {
53
+ if (!HashSet.is(u)) {
54
+ return ParseResult.fail(ParseError.TypeError(schema.ast, u));
79
55
  }
80
- out.add(tv.right);
81
- }
82
- return errors.isNonEmpty() ? ParseResult.failures(errors) : ParseResult.succeed(out.endMutation);
83
- });
84
- }
85
56
 
86
- function emptyNodeSchema<A>(_value: Schema<A>): Schema<EmptyNode<A>> {
87
- return Schema.struct({
88
- _tag: Schema.literal("EmptyNode"),
89
- modify: Schema.any,
90
- });
91
- }
92
-
93
- function leafNodeSchema<A>(value: Schema<A>): Schema<LeafNode<A>> {
94
- return Schema.struct({
95
- _tag: Schema.literal("LeafNode"),
96
- edit: Schema.number,
97
- hash: Schema.number,
98
- value: value,
99
- modify: Schema.any,
100
- });
101
- }
102
-
103
- function collisionNodeSchema<A>(value: Schema<A>): Schema<CollisionNode<A>> {
104
- return Schema.lazy(() =>
105
- Schema.struct({
106
- _tag: Schema.literal("CollisionNode"),
107
- edit: Schema.number,
108
- hash: Schema.number,
109
- children: nodeSchema(value).mutableArray,
110
- modify: Schema.any,
111
- }),
112
- );
113
- }
114
-
115
- function indexedNodeSchema<A>(value: Schema<A>): Schema<IndexedNode<A>> {
116
- return Schema.lazy(() =>
117
- Schema.struct({
118
- _tag: Schema.literal("IndexedNode"),
119
- edit: Schema.number,
120
- mask: Schema.number,
121
- children: nodeSchema(value).mutableArray,
122
- modify: Schema.any,
123
- }),
124
- );
125
- }
126
-
127
- function arrayNodeSchema<A>(value: Schema<A>): Schema<ArrayNode<A>> {
128
- return Schema.lazy(() =>
129
- Schema.struct({
130
- _tag: Schema.literal("ArrayNode"),
131
- edit: Schema.number,
132
- size: Schema.number,
133
- children: nodeSchema(value).mutableArray,
134
- modify: Schema.any,
135
- }),
136
- );
137
- }
138
-
139
- function nodeSchema<A>(value: Schema<A>): Schema<Node<A>> {
140
- return Schema.union(
141
- emptyNodeSchema(value),
142
- leafNodeSchema(value),
143
- collisionNodeSchema(value),
144
- indexedNodeSchema(value),
145
- arrayNodeSchema(value),
146
- );
147
- }
148
-
149
- function inline<A>(value: Schema<A>): Schema<HashSet<A>> {
150
- return Schema.struct({
151
- [HashSetTypeId]: Schema.uniqueSymbol(HashSetTypeId),
152
- [HashSetVariance]: Schema.any,
153
- _editable: Schema.boolean,
154
- _edit: Schema.number,
155
- config: Schema.any,
156
- _root: nodeSchema(value),
157
- _size: Schema.number,
158
- size: Schema.number,
159
- [Symbol.iterator]: Schema.any,
160
- [Symbol.hash]: Schema.any,
161
- [Symbol.equals]: Schema.any,
162
- });
57
+ const allErrors = options?.allErrors;
58
+ const errors = Vector.emptyPushable<KeyError>();
59
+ const out = HashSet.empty<unknown>().beginMutation;
60
+ for (const v of u) {
61
+ const tv = parseValue(v, options);
62
+ Either.concrete(tv);
63
+ if (tv.isLeft()) {
64
+ errors.push(ParseError.KeyError(value.ast, value, tv.left));
65
+ if (!allErrors) {
66
+ return ParseResult.fail(ParseError.IterableError(schema.ast, u, errors));
67
+ }
68
+ continue;
69
+ }
70
+ out.add(tv.right);
71
+ }
72
+ return errors.isNonEmpty()
73
+ ? ParseResult.fail(ParseError.IterableError(schema.ast, u, errors))
74
+ : ParseResult.succeed(out.endMutation);
75
+ });
76
+ };
163
77
  }
164
78
 
165
79
  function gen<A>(value: Gen<Sized, A>): Gen<Sized, HashSet<A>> {
@@ -1,10 +1,6 @@
1
1
  import type { Sized } from "@fncts/test/control/Sized";
2
2
 
3
- import {
4
- ImmutableArray,
5
- ImmutableArrayTypeId,
6
- ImmutableArrayVariance,
7
- } from "@fncts/base/collection/immutable/ImmutableArray";
3
+ import { ImmutableArray } from "@fncts/base/collection/immutable/ImmutableArray";
8
4
  import { Vector } from "@fncts/base/collection/immutable/Vector";
9
5
 
10
6
  /**
@@ -12,12 +8,9 @@ import { Vector } from "@fncts/base/collection/immutable/Vector";
12
8
  * @tsplus static fncts.schema.SchemaOps immutableArray
13
9
  */
14
10
  export function immutableArray<A>(value: Schema<A>): Schema<ImmutableArray<A>> {
15
- return Schema.declaration(
16
- Vector(value),
17
- inline(value),
18
- parser,
19
- ASTAnnotationMap.empty.annotate(ASTAnnotation.Identifier, "ImmutableArray").annotate(ASTAnnotation.GenHook, gen),
20
- );
11
+ return Schema.declaration(Vector(value), parser(true), parser(false))
12
+ .annotate(ASTAnnotation.Identifier, `ImmutableArray<${value.show()}>`)
13
+ .annotate(ASTAnnotation.GenHook, gen);
21
14
  }
22
15
 
23
16
  /**
@@ -45,42 +38,19 @@ export function deriveImmutableArray<A extends ImmutableArray<any>>(
45
38
  return unsafeCoerce(immutableArrayFromArray(value));
46
39
  }
47
40
 
48
- function parser<A>(value: Schema<A>): Parser<ImmutableArray<A>> {
49
- const schema = immutableArray(value);
50
- return Parser.make((u, options) => {
51
- if (!ImmutableArray.is(u)) {
52
- return ParseResult.fail(ParseError.TypeError(schema.ast, u));
53
- }
54
- const out: Array<A> = [];
55
- const errors = Vector.emptyPushable<ParseError>();
56
- const allErrors = options?.allErrors;
57
- const index = 0;
58
- for (const v of u) {
59
- const t = value.decode(v, options);
60
- Either.concrete(t);
61
- if (t.isLeft()) {
62
- errors.push(ParseError.IndexError(index, t.left.errors));
63
- if (allErrors) {
64
- continue;
65
- }
66
- return ParseResult.failures(errors);
67
- } else {
68
- out.push(t.right);
41
+ function parser(isDecoding: boolean) {
42
+ return <A>(value: Schema<A>): Parser<ImmutableArray<unknown>> => {
43
+ const schema = immutableArray(value);
44
+ const arraySchema = value.array;
45
+ const parse = isDecoding ? arraySchema.decode : arraySchema.encode;
46
+ return Parser.make((u, options) => {
47
+ if (!ImmutableArray.is(u)) {
48
+ return ParseResult.fail(ParseError.TypeError(schema.ast, u));
69
49
  }
70
- }
71
- return errors.isNonEmpty() ? ParseResult.failures(errors) : ParseResult.succeed(new ImmutableArray(out));
72
- });
73
- }
74
50
 
75
- function inline<A>(value: Schema<A>): Schema<ImmutableArray<A>> {
76
- return Schema.struct({
77
- [ImmutableArrayTypeId]: Schema.uniqueSymbol(ImmutableArrayTypeId),
78
- [ImmutableArrayVariance]: Schema.any,
79
- _array: Schema.array(value),
80
- [Symbol.equals]: Schema.any,
81
- [Symbol.hash]: Schema.any,
82
- [Symbol.iterator]: Schema.any,
83
- });
51
+ return parse(u, options).map((out) => new ImmutableArray(out as Array<unknown>));
52
+ });
53
+ };
84
54
  }
85
55
 
86
56
  function gen<A>(value: Gen<Sized, A>): Gen<Sized, ImmutableArray<A>> {
@@ -1,18 +1,14 @@
1
+ import type { IndexError } from "@fncts/schema/ParseError";
1
2
  import type { Sized } from "@fncts/test/control/Sized";
2
3
 
3
- import { ListTypeId } from "@fncts/base/collection/immutable/List";
4
-
5
4
  /**
6
5
  * @tsplus static fncts.schema.SchemaOps list
7
6
  * @tsplus getter fncts.Schema.Schema list
8
7
  */
9
8
  export function list<A>(value: Schema<A>): Schema<List<A>> {
10
- return Schema.declaration(
11
- Vector(value),
12
- inline(value),
13
- parser,
14
- ASTAnnotationMap.empty.annotate(ASTAnnotation.Identifier, "List").annotate(ASTAnnotation.GenHook, gen),
15
- );
9
+ return Schema.declaration(Vector(value), parser(true), parser(false))
10
+ .annotate(ASTAnnotation.Identifier, `List<${value.show()}>`)
11
+ .annotate(ASTAnnotation.GenHook, gen);
16
12
  }
17
13
 
18
14
  /**
@@ -40,55 +36,36 @@ export function deriveList<A extends List<any>>(
40
36
  return unsafeCoerce(listFromArray(value));
41
37
  }
42
38
 
43
- function parser<A>(value: Schema<A>): Parser<List<A>> {
44
- const schema = list(value);
45
- return Parser.make((u, options) => {
46
- if (!List.is(u)) {
47
- return ParseResult.fail(ParseError.TypeError(schema.ast, u));
48
- }
49
- const out = new ListBuffer<A>();
50
- const errors = Vector.emptyPushable<ParseError>();
51
- const allErrors = options?.allErrors;
52
- const index = 0;
53
- for (const v of u) {
54
- const t = value.decode(v, options);
55
- Either.concrete(t);
56
- if (t.isLeft()) {
57
- errors.push(ParseError.IndexError(index, t.left.errors));
58
- if (allErrors) {
59
- continue;
39
+ function parser(isDecoding: boolean) {
40
+ return <A>(value: Schema<A>): Parser<List<unknown>> => {
41
+ const schema = list(value);
42
+ const parseValue = isDecoding ? value.decode : value.encode;
43
+ return Parser.make((u, options) => {
44
+ if (!List.is(u)) {
45
+ return ParseResult.fail(ParseError.TypeError(schema.ast, u));
46
+ }
47
+ const out = new ListBuffer<unknown>();
48
+ const errors = Vector.emptyPushable<IndexError>();
49
+ const allErrors = options?.allErrors;
50
+ const index = 0;
51
+ for (const v of u) {
52
+ const t = parseValue(v, options);
53
+ Either.concrete(t);
54
+ if (t.isLeft()) {
55
+ errors.push(ParseError.IndexError(index, t.left));
56
+ if (allErrors) {
57
+ continue;
58
+ }
59
+ return ParseResult.fail(ParseError.IterableError(schema.ast, u, errors));
60
+ } else {
61
+ out.append(t.right);
60
62
  }
61
- return ParseResult.failures(errors);
62
- } else {
63
- out.append(t.right);
64
63
  }
65
- }
66
- return errors.isNonEmpty() ? ParseResult.failures(errors) : ParseResult.succeed(out.toList);
67
- });
68
- }
69
-
70
- function nil<A>(_value: Schema<A>): Schema<Nil<A>> {
71
- return Schema.struct({
72
- _tag: Schema.literal("Nil"),
73
- [ListTypeId]: Schema.uniqueSymbol(ListTypeId),
74
- [Symbol.iterator]: Schema.any,
75
- });
76
- }
77
-
78
- function cons<A>(value: Schema<A>): Schema<Cons<A>> {
79
- return Schema.lazy(() =>
80
- Schema.struct({
81
- _tag: Schema.literal("Cons"),
82
- [ListTypeId]: Schema.uniqueSymbol(ListTypeId),
83
- [Symbol.iterator]: Schema.any,
84
- head: value,
85
- tail: inline(value),
86
- }),
87
- );
88
- }
89
-
90
- function inline<A>(value: Schema<A>): Schema<List<A>> {
91
- return Schema.lazy(() => Schema.union(nil(value), cons(value)));
64
+ return errors.isNonEmpty()
65
+ ? ParseResult.fail(ParseError.IterableError(schema.ast, u, errors))
66
+ : ParseResult.succeed(out.toList);
67
+ });
68
+ };
92
69
  }
93
70
 
94
71
  function gen<A>(value: Gen<Sized, A>): Gen<Sized, List<A>> {
@@ -0,0 +1,93 @@
1
+ import type { KeyError } from "@fncts/schema/ParseError";
2
+ import type { Sized } from "@fncts/test/control/Sized";
3
+
4
+ /**
5
+ * @tsplus static fncts.schema.SchemaOps map
6
+ */
7
+ export function map<K, V>(key: Schema<K>, value: Schema<V>): Schema<Map<K, V>> {
8
+ return Schema.declaration(Vector(key, value), mapParser(true), mapParser(false))
9
+ .annotate(ASTAnnotation.Identifier, `Map<${key.show()}, ${value.show()}>`)
10
+ .annotate(ASTAnnotation.GenHook, gen);
11
+ }
12
+
13
+ /**
14
+ * @tsplus static fncts.schema.SchemaOps mapFromRecord
15
+ */
16
+ export function mapFromRecord<K extends string | symbol, V>(key: Schema<K>, value: Schema<V>): Schema<Map<K, V>> {
17
+ return Schema.record(key, value).transform(
18
+ map(key, value),
19
+ (input) => {
20
+ const out = new Map<K, V>();
21
+ for (const [k, v] of Object.entries(input)) {
22
+ out.set(k as K, v as V);
23
+ }
24
+ return out;
25
+ },
26
+ (input) => {
27
+ const out = {} as Record<K, V>;
28
+ input.forEach((v, k) => {
29
+ out[k] = v;
30
+ });
31
+ return out;
32
+ },
33
+ );
34
+ }
35
+
36
+ /**
37
+ * @tsplus derive fncts.schema.Schema[fncts.Map]<_> 10
38
+ */
39
+ export function deriveMap<A extends Map<any, any>>(
40
+ // @ts-expect-error
41
+ ...[key, value]: [A] extends [Map<infer K, infer V>]
42
+ ? Check<Check.IsEqual<A, Map<K, V>> & Check.Extends<K, string | symbol>> extends Check.True
43
+ ? [key: Schema<K>, value: Schema<V>]
44
+ : never
45
+ : never
46
+ ): Schema<A> {
47
+ return unsafeCoerce(mapFromRecord(key as Schema<string | symbol>, value));
48
+ }
49
+
50
+ function mapParser(isDecoding: boolean) {
51
+ return <K, V>(key: Schema<K>, value: Schema<V>): Parser<Map<unknown, unknown>> => {
52
+ const schema = map(key, value);
53
+ return Parser.make((u, options) => {
54
+ if (!(u instanceof Map)) {
55
+ return ParseResult.fail(ParseError.TypeError(schema.ast, u));
56
+ }
57
+ const allErrors = options?.allErrors;
58
+ const errors = Vector.emptyPushable<KeyError>();
59
+ const out = new Map();
60
+ const keyParser = isDecoding ? key.decode : key.encode;
61
+ const valueParser = isDecoding ? value.decode : value.encode;
62
+ for (const [k, v] of u) {
63
+ const tk = keyParser(k, options);
64
+ Either.concrete(tk);
65
+ if (tk.isLeft()) {
66
+ errors.push(ParseError.KeyError(key.ast, k, tk.left));
67
+ if (!allErrors) {
68
+ return ParseResult.fail(ParseError.IterableError(schema.ast, u, errors));
69
+ }
70
+ }
71
+ const tv = valueParser(v, options);
72
+ Either.concrete(tv);
73
+ if (tv.isLeft()) {
74
+ errors.push(ParseError.KeyError(key.ast, k, ParseError.TypeError(value.ast, tv.left)));
75
+ if (!allErrors) {
76
+ return ParseResult.fail(ParseError.IterableError(schema.ast, u, errors));
77
+ }
78
+ }
79
+ if (tk.isLeft() || tv.isLeft()) {
80
+ continue;
81
+ }
82
+ out.set(tk.right, tv.right);
83
+ }
84
+ return errors.isNonEmpty()
85
+ ? ParseResult.fail(ParseError.IterableError(schema.ast, u, errors))
86
+ : ParseResult.succeed(out);
87
+ });
88
+ };
89
+ }
90
+
91
+ function gen<K, V>(key: Gen<Sized, K>, value: Gen<Sized, V>): Gen<Sized, Map<K, V>> {
92
+ return Gen.array(Gen.tuple(key, value)).map((pairs) => new Map(pairs));
93
+ }