| -- Copyright 2020 The Fuchsia Authors. All rights reserved. |
| -- Use of this source code is governed by a BSD-style license that can be |
| -- found in the LICENSE file. |
| |
| |
| module Mode exposing |
| ( Map |
| , Mode(..) |
| , decode |
| , decodeMap |
| , defaultInput |
| , defaultOutput |
| , empty |
| , encode |
| , encodeMap |
| , get |
| , inputs |
| , insert |
| , nextInput |
| , nextOutput |
| , options |
| , outputs |
| , previousInput |
| , previousOutput |
| , singleton |
| , title |
| ) |
| |
| {-| This module defines the Mode type. |
| |
| A mode is a format supported by fidlbolt. Some of them, like Fidl and Go, |
| directly correspond to file types. Others, like BytesPlus and Diff, are more |
| like abstract parsers/targets. |
| |
| In fidlbolt, the user selects an input and output mode. Only some input modes |
| are allowed, and for a given input mode only a some output modes are allowed. |
| The core functionality of the app is implemented in a set of input-output |
| transformations. For example, (Fidl, Json) compiles a FIDL file with fidlc; |
| (Bytes, FidlText) attemps to decode bytes (represented in hex) to FIDL Text. |
| |
| -} |
| |
| import Dict exposing (Dict) |
| import Form exposing (Form) |
| import Json.Decode as Decode |
| import Json.Encode as Encode |
| |
| |
| |
| ------------- MODE ------------------------------------------------------------- |
| |
| |
| type Mode |
| = Bytes |
| | BytesPlus |
| | C |
| | Dart |
| | Diff |
| | Fidl |
| | FidlText |
| | Go |
| | Hlcpp |
| | Json |
| | Llcpp |
| | Rust |
| |
| |
| inputs : List Mode |
| inputs = |
| [ Fidl, FidlText, Bytes ] |
| |
| |
| outputs : Mode -> List Mode |
| outputs input = |
| case input of |
| Fidl -> |
| [ Fidl, Json, C, Llcpp, Hlcpp, Rust, Go, Dart ] |
| |
| FidlText -> |
| -- TODO(mkember): Add BytesPlus once implemented. |
| [ FidlText, Bytes ] |
| |
| Bytes -> |
| -- TODO(mkember): Add BytesPlus once implemented. |
| [ Bytes, Diff, FidlText ] |
| |
| _ -> |
| [] |
| |
| |
| defaultInput : Mode |
| defaultInput = |
| Fidl |
| |
| |
| defaultOutput : Mode -> Mode |
| defaultOutput input = |
| case input of |
| Fidl -> |
| Json |
| |
| FidlText -> |
| Bytes |
| |
| Bytes -> |
| Bytes |
| |
| _ -> |
| input |
| |
| |
| nextInput : Mode -> Mode |
| nextInput input = |
| Maybe.withDefault input (getNext input inputs) |
| |
| |
| previousInput : Mode -> Mode |
| previousInput input = |
| Maybe.withDefault input (getPrevious input inputs) |
| |
| |
| nextOutput : Mode -> Mode -> Mode |
| nextOutput input output = |
| Maybe.withDefault output (getNext output (outputs input)) |
| |
| |
| previousOutput : Mode -> Mode -> Mode |
| previousOutput input output = |
| Maybe.withDefault output (getPrevious output (outputs input)) |
| |
| |
| getNext : a -> List a -> Maybe a |
| getNext item list = |
| let |
| rec restOfList = |
| case restOfList of |
| [] -> |
| Nothing |
| |
| [ last ] -> |
| if last == item then |
| List.head list |
| |
| else |
| Nothing |
| |
| first :: second :: rest -> |
| if first == item then |
| Just second |
| |
| else |
| rec (second :: rest) |
| in |
| rec list |
| |
| |
| getPrevious : a -> List a -> Maybe a |
| getPrevious item list = |
| getNext item (List.reverse list) |
| |
| |
| {-| Returns a form containing options for the given input-output transformation. |
| These get passed along to the server and affect its response. |
| -} |
| options : Mode -> Mode -> Form |
| options input output = |
| let |
| files default others = |
| Form.select "file" "File" (default :: others) (Tuple.first default) |
| |
| entries = |
| case ( input, output ) of |
| ( Fidl, Fidl ) -> |
| [ Form.checkbox "lint" "Lint" False ] |
| |
| ( Fidl, Json ) -> |
| [ files ( "ir", "Library IR" ) |
| [ ( "schema", "Schema" ) |
| , ( "deps", "Dependencies" ) |
| ] |
| ] |
| |
| ( Fidl, Hlcpp ) -> |
| [ files ( "header", "Header" ) |
| [ ( "source", "Source" ) |
| , ( "tables", "Tables" ) |
| ] |
| ] |
| |
| ( Fidl, Llcpp ) -> |
| [ files ( "header", "Header" ) |
| [ ( "source", "Source" ) |
| , ( "test", "Test base" ) |
| , ( "tables", "Tables" ) |
| ] |
| ] |
| |
| ( Fidl, C ) -> |
| [ files ( "header", "Header" ) |
| [ ( "client", "Client" ) |
| , ( "server", "Server" ) |
| , ( "tables", "Tables" ) |
| ] |
| ] |
| |
| ( Fidl, Dart ) -> |
| [ files ( "library", "Library" ) |
| [ ( "test", "Test base" ) ] |
| ] |
| |
| ( _, Bytes ) -> |
| [ Form.number "columns" "Columns" 8 (\n -> n > 0) |
| , Form.number "group" "Grouping" 2 (\n -> n > 0) |
| , Form.checkbox "offsets" "Line offsets" True |
| , Form.checkbox "capital" "Capital hex" False |
| , Form.checkbox "ascii" "ASCII" False |
| ] |
| |
| ( Bytes, Diff ) -> |
| [ Form.text "separator" "Separator" ";" |
| ] |
| |
| _ -> |
| [] |
| in |
| Form.define entries |
| |
| |
| |
| ------------- MAP -------------------------------------------------------------- |
| |
| |
| {-| A mapping from modes to a. The key type is String rather than Mode because |
| non-String keys don't work well in Elm (they aren't comparable). |
| -} |
| type alias Map a = |
| Dict String a |
| |
| |
| empty : Map a |
| empty = |
| Dict.empty |
| |
| |
| singleton : Mode -> a -> Map a |
| singleton mode value = |
| Dict.singleton (toString mode) value |
| |
| |
| get : Mode -> Map a -> Maybe a |
| get mode = |
| Dict.get (toString mode) |
| |
| |
| insert : Mode -> a -> Map a -> Map a |
| insert mode value map = |
| Dict.insert (toString mode) value map |
| |
| |
| |
| ------------- ENCODE / DECODE -------------------------------------------------- |
| |
| |
| encode : Mode -> Encode.Value |
| encode mode = |
| Encode.string (toString mode) |
| |
| |
| decode : Decode.Decoder Mode |
| decode = |
| Decode.andThen |
| (\string -> |
| case fromString string of |
| Just mode -> |
| Decode.succeed mode |
| |
| Nothing -> |
| Decode.fail ("Invalid mode: " ++ string) |
| ) |
| Decode.string |
| |
| |
| encodeMap : (a -> Encode.Value) -> Map a -> Encode.Value |
| encodeMap encoder map = |
| Encode.dict identity encoder map |
| |
| |
| decodeMap : Decode.Decoder a -> Decode.Decoder (Map a) |
| decodeMap decoder = |
| Decode.dict decoder |
| |
| |
| |
| ------------- STRING FUNCTIONS ------------------------------------------------- |
| |
| |
| toString : Mode -> String |
| toString mode = |
| case mode of |
| Bytes -> |
| "bytes" |
| |
| BytesPlus -> |
| "bytes+" |
| |
| C -> |
| "c" |
| |
| Dart -> |
| "dart" |
| |
| Diff -> |
| "diff" |
| |
| Fidl -> |
| "fidl" |
| |
| FidlText -> |
| "fidltext" |
| |
| Go -> |
| "go" |
| |
| Hlcpp -> |
| "hlcpp" |
| |
| Json -> |
| "json" |
| |
| Llcpp -> |
| "llcpp" |
| |
| Rust -> |
| "rust" |
| |
| |
| fromString : String -> Maybe Mode |
| fromString string = |
| case string of |
| "bytes" -> |
| Just Bytes |
| |
| "bytes+" -> |
| Just BytesPlus |
| |
| "c" -> |
| Just C |
| |
| "dart" -> |
| Just Dart |
| |
| "diff" -> |
| Just Diff |
| |
| "fidl" -> |
| Just Fidl |
| |
| "fidltext" -> |
| Just FidlText |
| |
| "go" -> |
| Just Go |
| |
| "hlcpp" -> |
| Just Hlcpp |
| |
| "json" -> |
| Just Json |
| |
| "llcpp" -> |
| Just Llcpp |
| |
| "rust" -> |
| Just Rust |
| |
| _ -> |
| Nothing |
| |
| |
| title : Mode -> String |
| title mode = |
| case mode of |
| Bytes -> |
| "Bytes" |
| |
| BytesPlus -> |
| "Bytes+" |
| |
| C -> |
| "C" |
| |
| Dart -> |
| "Dart" |
| |
| Diff -> |
| "Diff" |
| |
| Fidl -> |
| "FIDL" |
| |
| FidlText -> |
| "FIDL Text" |
| |
| Go -> |
| "Go" |
| |
| Hlcpp -> |
| "HLCPP" |
| |
| Json -> |
| "JSON" |
| |
| Llcpp -> |
| "LLCPP" |
| |
| Rust -> |
| "Rust" |