diff options
author | Louis Pilfold <louis@lpil.uk> | 2024-11-25 22:38:01 +0000 |
---|---|---|
committer | Louis Pilfold <louis@lpil.uk> | 2024-12-22 10:56:21 +0000 |
commit | f5585adfb4a969d9167817041af0e8c4334e84ec (patch) | |
tree | 901a9b1451d24e87fe27d97bb74e36fa1477d8ac /src/gleam_stdlib_decode_ffi.mjs | |
parent | d50616d7b5bde1eeab972a989abcd288c4af536b (diff) | |
download | gleam_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.mjs | 68 |
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(); +} |