From ea9704d51d72f63d6dae4bc18c5b5d88deaf0d6b Mon Sep 17 00:00:00 2001 From: Rupert Smith Date: Wed, 3 Dec 2025 16:43:56 +0000 Subject: [PATCH] Enabling Byte over ports in the compiler. Injecting _Json_encodeBytes and _Json_decodeBytes kernel functions directly, not through a customized Json package. --- src/Compiler/Canonicalize/Effects.elm | 10 +++++++- src/Compiler/Data/Name.elm | 12 +++++++++ src/Compiler/Generate/JavaScript.elm | 25 ++++++++++++++++++- src/Compiler/Guida/ModuleName.elm | 10 ++++++++ src/Compiler/Guida/Package.elm | 6 +++++ src/Compiler/Optimize/Port.elm | 20 +++++++++++++++ src/Compiler/Reporting/Error/Canonicalize.elm | 2 +- 7 files changed, 82 insertions(+), 3 deletions(-) diff --git a/src/Compiler/Canonicalize/Effects.elm b/src/Compiler/Canonicalize/Effects.elm index de7e2943a..b90c37140 100644 --- a/src/Compiler/Canonicalize/Effects.elm +++ b/src/Compiler/Canonicalize/Effects.elm @@ -207,7 +207,7 @@ checkPayload tipe = Can.TType home name args -> case args of [] -> - if isJson home name || isString home name || isIntFloatBool home name then + if isJson home name || isString home name || isIntFloatBool home name || isBytes home name then Ok () else @@ -306,3 +306,11 @@ isArray home name = == ModuleName.array && name == Name.array + + +isBytes : IO.Canonical -> Name.Name -> Bool +isBytes home name = + home + == ModuleName.bytes + && name + == Name.bytes diff --git a/src/Compiler/Data/Name.elm b/src/Compiler/Data/Name.elm index a6297b81f..70c5a1875 100644 --- a/src/Compiler/Data/Name.elm +++ b/src/Compiler/Data/Name.elm @@ -4,6 +4,7 @@ module Compiler.Data.Name exposing , basics , bitwise , bool + , bytes , char , cmd , debug @@ -28,6 +29,7 @@ module Compiler.Data.Name exposing , isKernel , isNumberType , jsArray + , json , list , mainModule , main_ @@ -356,6 +358,11 @@ dict = "Dict" +bytes : Name +bytes = + "Bytes" + + tuple : Name tuple = "Tuple" @@ -366,6 +373,11 @@ jsArray = "JsArray" +json : Name +json = + "Json" + + task : Name task = "Task" diff --git a/src/Compiler/Generate/JavaScript.elm b/src/Compiler/Generate/JavaScript.elm index f57e75937..eccbdc5cc 100644 --- a/src/Compiler/Generate/JavaScript.elm +++ b/src/Compiler/Generate/JavaScript.elm @@ -267,7 +267,30 @@ emptyState startingLine = stateToBuilder : State -> String stateToBuilder (State (JS.Builder revKernels code _ _ _) _) = - prependBuilders revKernels code + prependBuilders revKernels (bytesForPorts ++ code) + + +bytesForPorts : String +bytesForPorts = + """ +// BYTES FOR PORTS +var _Json_decodeBytes = _Json_decodePrim(function(value) { + if (value instanceof Uint8Array) { + return $elm$core$Result$Ok(new DataView(value.buffer, value.byteOffset, value.byteLength)); + } + if (value instanceof ArrayBuffer) { + return $elm$core$Result$Ok(new DataView(value)); + } + if (value instanceof DataView) { + return $elm$core$Result$Ok(value); + } + return _Json_expecting('a BYTES value (Uint8Array, ArrayBuffer, or DataView)', value); +}); + +var _Json_encodeBytes = function(bytes) { + return _Json_wrap(new Uint8Array(bytes.buffer, bytes.byteOffset, bytes.byteLength)); +}; +""" prependBuilders : List String -> String -> String diff --git a/src/Compiler/Guida/ModuleName.elm b/src/Compiler/Guida/ModuleName.elm index 9750ec319..f29771159 100644 --- a/src/Compiler/Guida/ModuleName.elm +++ b/src/Compiler/Guida/ModuleName.elm @@ -2,6 +2,7 @@ module Compiler.Guida.ModuleName exposing ( Raw , array , basics + , bytes , canonicalDecoder , canonicalEncoder , char @@ -283,6 +284,15 @@ jsonEncode = +-- BYTES + + +bytes : Canonical +bytes = + Canonical Pkg.bytes "Bytes" + + + -- WEBGL diff --git a/src/Compiler/Guida/Package.elm b/src/Compiler/Guida/Package.elm index be8e9c8c0..c350a5551 100644 --- a/src/Compiler/Guida/Package.elm +++ b/src/Compiler/Guida/Package.elm @@ -3,6 +3,7 @@ module Compiler.Guida.Package exposing , Name , Project , browser + , bytes , compareName , core , decoder @@ -144,6 +145,11 @@ json = toName elm "json" +bytes : Name +bytes = + toName elm "bytes" + + http : Name http = toName elm "http" diff --git a/src/Compiler/Optimize/Port.elm b/src/Compiler/Optimize/Port.elm index 2bb0f4558..9afcb07f1 100644 --- a/src/Compiler/Optimize/Port.elm +++ b/src/Compiler/Optimize/Port.elm @@ -58,6 +58,9 @@ toEncoder tipe = else if name == Name.value then Names.registerGlobal A.zero ModuleName.basics Name.identity_ + else if name == Name.bytes then + encodeBytes + else crash "toEncoder: bad custom type" @@ -271,6 +274,9 @@ toDecoder tipe = ( "Value", [] ) -> decode "value" + ( "Bytes", [] ) -> + decodeBytes + ( "Maybe", [ arg ] ) -> decodeMaybe arg @@ -478,3 +484,17 @@ encode name = decode : Name -> Names.Tracker Opt.Expr decode name = Names.registerGlobal A.zero ModuleName.jsonDecode name + + + +-- BYTES HELPERS + + +encodeBytes : Names.Tracker Opt.Expr +encodeBytes = + Names.registerKernel Name.json (Opt.VarKernel A.zero Name.json "encodeBytes") + + +decodeBytes : Names.Tracker Opt.Expr +decodeBytes = + Names.registerKernel Name.json (Opt.VarKernel A.zero Name.json "decodeBytes") diff --git a/src/Compiler/Reporting/Error/Canonicalize.elm b/src/Compiler/Reporting/Error/Canonicalize.elm index 1d1bc94fe..ad2aa09ad 100644 --- a/src/Compiler/Reporting/Error/Canonicalize.elm +++ b/src/Compiler/Reporting/Error/Canonicalize.elm @@ -704,7 +704,7 @@ toReport source err = [ D.reflow "I cannot handle that. The types that CAN flow in and out of Guida include:" , D.indent 4 <| D.reflow - "Ints, Floats, Bools, Strings, Maybes, Lists, Arrays, tuples, records, and JSON values." + "Ints, Floats, Bools, Strings, Maybes, Lists, Arrays, tuples, records, JSON values, and Bytes." , D.reflow "Since JSON values can flow through, you can use JSON encoders and decoders to allow other types through as well. More advanced users often just do everything with encoders and decoders for more control and better errors." ]