aboutsummaryrefslogtreecommitdiff
path: root/src/gleam_stdlib_decode_ffi.mjs
diff options
context:
space:
mode:
authorLouis Pilfold <louis@lpil.uk>2024-11-25 22:38:01 +0000
committerLouis Pilfold <louis@lpil.uk>2024-12-22 10:56:21 +0000
commitf5585adfb4a969d9167817041af0e8c4334e84ec (patch)
tree901a9b1451d24e87fe27d97bb74e36fa1477d8ac /src/gleam_stdlib_decode_ffi.mjs
parentd50616d7b5bde1eeab972a989abcd288c4af536b (diff)
downloadgleam_stdlib-f5585adfb4a969d9167817041af0e8c4334e84ec.tar.gz
gleam_stdlib-f5585adfb4a969d9167817041af0e8c4334e84ec.zip
New decode module
Diffstat (limited to 'src/gleam_stdlib_decode_ffi.mjs')
-rw-r--r--src/gleam_stdlib_decode_ffi.mjs68
1 files changed, 68 insertions, 0 deletions
diff --git a/src/gleam_stdlib_decode_ffi.mjs b/src/gleam_stdlib_decode_ffi.mjs
new file mode 100644
index 0000000..86c9c60
--- /dev/null
+++ b/src/gleam_stdlib_decode_ffi.mjs
@@ -0,0 +1,68 @@
+import { Ok, Error, List, NonEmpty } from "./gleam.mjs";
+import { default as Dict } from "./dict.mjs";
+import { Some, None } from "./gleam/option.mjs";
+import { DecodeError, classify } from "./gleam/dynamic.mjs";
+
+export function strict_index(data, key) {
+ const int = Number.isInteger(key);
+
+ // Dictionaries and dictionary-like objects can be indexed
+ if (data instanceof Dict || data instanceof WeakMap || data instanceof Map) {
+ const token = {};
+ const entry = data.get(key, token);
+ if (entry === token) return new Ok(new None());
+ return new Ok(new Some(entry));
+ }
+
+ // The first 3 elements of lists can be indexed
+ if ((key === 0 || key === 1 || key === 2) && data instanceof List) {
+ let i = 0;
+ for (const value of data) {
+ if (i === key) return new Ok(new Some(value));
+ i++;
+ }
+ return new Error("Indexable");
+ }
+
+ // Arrays and objects can be indexed
+ if (
+ (int && Array.isArray(data)) ||
+ (data && typeof data === "object") ||
+ (data && Object.getPrototypeOf(data) === Object.prototype)
+ ) {
+ if (key in data) return new Ok(new Some(data[key]));
+ return new Ok(new None());
+ }
+
+ return new Error(int ? "Indexable" : "Dict");
+}
+
+export function list(data, decode, pushPath, index, emptyList) {
+ if (!(data instanceof List || Array.isArray(data))) {
+ let error = new DecodeError("List", classify(data), emptyList);
+ return [emptyList, List.fromArray([error])];
+ }
+
+ const decoded = [];
+
+ for (const element of data) {
+ const layer = decode(element);
+ const [out, errors] = layer;
+
+ if (errors instanceof NonEmpty) {
+ const [_, errors] = pushPath(layer, index.toString());
+ return [emptyList, errors];
+ }
+ decoded.push(out);
+ index++;
+ }
+
+ return [List.fromArray(decoded), emptyList];
+}
+
+export function dict(data) {
+ if (data instanceof Dict) {
+ return new Ok(data);
+ }
+ return new Error();
+}