1 module Voting.Protocol.Version where
3 import Data.Foldable (any)
4 import Data.List (List)
7 import Voting.Protocol.Arithmetic
10 -- | Version of the Helios-C protocol.
11 data Version = Version
12 { version_branch :: List Natural
13 , version_tags :: List { tag :: String, tagNum :: Natural }
16 instance IsString Version where
17 fromString = fromJust . readVersion
18 instance Show Version where
19 showsPrec _p Version{..} =
21 (List.intersperse (showChar '.') $
22 shows <$> version_branch) .
24 ((\(t,n) -> showChar '-' . showString (Text.unpack t) .
25 if n > 0 then shows n else id)
27 instance ToJSON Version where
28 toJSON = toJSON . show
29 toEncoding = toEncoding . show
30 instance FromJSON Version where
31 parseJSON (JSON.String s)
32 | Just v <- readVersion (Text.unpack s)
34 parseJSON json = JSON.typeMismatch "Version" json
37 hasVersionTag :: Version -> String -> Boolean
38 hasVersionTag (Version v) tag = any (\{tag:t} -> t == tag) v.version_tags
40 -- ** Type 'ExperimentalVersion'
41 type ExperimentalVersion = V [1,6] '[ '(VersionTagQuicker,0)]
42 experimentalVersion :: Version
43 experimentalVersion = stableVersion{version_tags = [(versionTagQuicker,0)]}
45 -- ** Type 'StableVersion'
46 type StableVersion = V [1,6] '[]
47 stableVersion :: Version
50 -- ** Type 'VersionTagQuicker'
51 type VersionTagQuicker = "quicker"
53 versionTagQuicker :: String
54 versionTagQuicker = "quicker"
56 readVersion :: String -> Maybe Version
57 readVersion = parseReadP $ do
58 version_branch <- Read.sepBy1
59 (Read.read <$> Read.munch1 Char.isDigit)
61 version_tags <- Read.many $ (,)
62 <$> (Text.pack <$ Read.char '-' <*> Read.munch1 Char.isAlpha)
63 <*> (Read.read <$> Read.munch1 Char.isDigit <|> return 0)
67 -- | Type-level representation of a specific 'Version'.
68 data V (branch::[Nat]) (tags::[(Symbol,Nat)])
69 -- | Like a normal 'reflect' but this one takes
70 -- its 'Version' from a type-level 'V'ersion
71 -- instead of a term-level 'Version'.
72 instance (VersionBranchVal branch, VersionTagsVal tags) => Reifies (V branch tags) Version where
74 { version_branch = versionBranchVal (Proxy @branch)
75 , version_tags = versionTagsVal (Proxy @tags)
78 -- *** Class 'VersionBranchVal'
79 class VersionBranchVal a where
80 versionBranchVal :: proxy a -> [Natural]
81 instance KnownNat h => VersionBranchVal '[h] where
82 versionBranchVal _ = [fromIntegral (natVal (Proxy @h))]
86 , VersionBranchVal (hh ':t)
87 ) => VersionBranchVal (h ': hh ': t) where
89 fromIntegral (natVal (Proxy @h)) :
90 versionBranchVal (Proxy @(hh ':t))
92 -- *** Class 'VersionTagsVal'
93 class VersionTagsVal a where
94 versionTagsVal :: proxy a -> [(Text,Natural)]
95 instance VersionTagsVal '[] where
101 ) => VersionTagsVal ('(s,n) ': t) where
103 ( Text.pack (symbolVal (Proxy @s))
104 , fromIntegral (natVal (Proxy @n))
105 ) : versionTagsVal (Proxy :: Proxy t)