-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathhcandid.hs
67 lines (61 loc) · 2.14 KB
/
hcandid.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
{-# LANGUAGE OverloadedStrings #-}
import qualified Data.ByteString.Builder as BS
import qualified Data.ByteString.Lazy as BS
import qualified Data.Text as T
import qualified Text.Hex as T
import Options.Applicative
import Control.Monad
import Codec.Candid
import Data.Char
import System.IO
import System.Exit
import Prettyprinter
import Prettyprinter.Util
err :: String -> IO b
err s = hPutStr stderr s >> exitFailure
fromHex :: String -> IO BS.ByteString
fromHex = maybe (err "Invalid hex data") (return . BS.fromStrict) . T.decodeHex . T.pack . filter (not . isSpace)
fromRust :: String -> IO BS.ByteString
fromRust = go
where
go :: String -> IO BS.ByteString
go "" = return mempty
go ('\\':'x':h1:h2:xs)
| Just b <- T.decodeHex (T.pack [h1,h2])
= (BS.fromStrict b <>) <$> go xs
go ('\\':c:xs)
| ord c <= 0xff
= (BS.singleton (fromIntegral (ord c)) <>) <$> go xs
go (c:xs)
| ord c <= 0xff
= (BS.singleton (fromIntegral (ord c)) <>) <$> go xs
go xs = err $ "Stuck parsing rust string at\n" <> xs
decodeCandid :: BS.ByteString -> IO ()
decodeCandid b = case decodeVals b of
Left msg -> err msg
Right (_, vs) -> putDocW 80 (pretty vs) >> putStrLn ""
encodeCandid :: String -> IO ()
encodeCandid txt = case parseValues txt of
Left msg -> err msg
Right vs -> case encodeDynValues vs of
Left msg -> err msg
Right b -> BS.putStr (BS.toLazyByteString b)
main :: IO ()
main = join . customExecParser (prefs showHelpOnError) $
info (helper <*> parser)
( fullDesc
<> header "Candid tooling"
-- <> progDesc "A stand-alone local reference implementation of the Internet Computer"
)
where
parser :: Parser (IO ())
parser =
(decodeCandid =<<) <$> (
flag' () (long "decode" <> help "Decode bytes to Candid")
*> (
fromHex <$> strOption (long "hex" <> help "parse hex data")
<|> fromRust <$> strOption (long "rust" <> help "parse text with \\xFF escapes")
<|> flag' BS.getContents (long "stdin" <> help "read data from stdin")
)
) <|>
encodeCandid <$> strOption (long "encode" <> help "encode Candid textual form, at inferred type)")