-
Notifications
You must be signed in to change notification settings - Fork 63
/
ByteString.hs
107 lines (89 loc) · 3.02 KB
/
ByteString.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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-}
module Plutarch.ByteString (
PByteString,
phexByteStr,
pbyteStr,
pconsBS,
psliceBS,
plengthBS,
pindexBS,
) where
import Data.ByteString (ByteString)
import qualified Data.ByteString as BS
import Data.Char (toLower)
import Data.Word (Word8)
import GHC.Stack (HasCallStack)
import Plutarch (punsafeBuiltin)
import Plutarch.Bool (PEq, POrd, (#<), (#<=), (#==))
import Plutarch.Integer (PInteger)
import Plutarch.Lift (
DerivePConstantViaCoercible (DerivePConstantViaCoercible),
PConstant,
PLifted,
PUnsafeLiftDecl,
pconstant,
)
import Plutarch.Prelude
import qualified PlutusCore as PLC
-- | Plutus 'BuiltinByteString'
data PByteString s
instance PUnsafeLiftDecl PByteString where type PLifted PByteString = ByteString
deriving via (DerivePConstantViaCoercible ByteString PByteString ByteString) instance (PConstant ByteString)
instance PEq PByteString where
x #== y = punsafeBuiltin PLC.EqualsByteString # x # y
instance POrd PByteString where
x #<= y = punsafeBuiltin PLC.LessThanEqualsByteString # x # y
x #< y = punsafeBuiltin PLC.LessThanByteString # x # y
instance Semigroup (Term s PByteString) where
x <> y = punsafeBuiltin PLC.AppendByteString # x # y
instance Monoid (Term s PByteString) where
mempty = pconstant BS.empty
-- | Interpret a hex string as a PByteString.
phexByteStr :: HasCallStack => String -> Term s PByteString
phexByteStr = pconstant . BS.pack . f
where
f "" = []
f [_] = error "UnevenLength"
f (x : y : rest) = (hexDigitToWord8 x * 16 + hexDigitToWord8 y) : f rest
{-# DEPRECATED pbyteStr "Use `pconstant` instead." #-}
-- | Construct a PByteString term from a Haskell bytestring.
pbyteStr :: ByteString -> Term s PByteString
pbyteStr = pconstant
-----------------------------------------------------------
-- The following functions should be import qualified. --
-----------------------------------------------------------
-- | Prepend a byte, represented by a non negative 'PInteger', to a 'PBytestring'.
pconsBS :: Term s (PInteger :--> PByteString :--> PByteString)
pconsBS = punsafeBuiltin PLC.ConsByteString
{- | Slice a 'PByteString' with given start index and slice length.
>>> (pslice # 2 # 3 phexByteStr "4102afde5b2a") #== phexByteStr "afde5b"
-}
psliceBS :: Term s (PInteger :--> PInteger :--> PByteString :--> PByteString)
psliceBS = punsafeBuiltin PLC.SliceByteString
-- | Find the length of a 'PByteString'.
plengthBS :: Term s (PByteString :--> PInteger)
plengthBS = punsafeBuiltin PLC.LengthOfByteString
-- | 'PByteString' indexing function.
pindexBS :: Term s (PByteString :--> PInteger :--> PInteger)
pindexBS = punsafeBuiltin PLC.IndexByteString
hexDigitToWord8 :: HasCallStack => Char -> Word8
hexDigitToWord8 = f . toLower
where
f '0' = 0
f '1' = 1
f '2' = 2
f '3' = 3
f '4' = 4
f '5' = 5
f '6' = 6
f '7' = 7
f '8' = 8
f '9' = 9
f 'a' = 10
f 'b' = 11
f 'c' = 12
f 'd' = 13
f 'e' = 14
f 'f' = 15
f c = error $ "InvalidHexDigit " ++ [c]