on master help sign in
start using D.customString in Elm.Version

Also expose V.parser for cases like "author/project@X.Y.Z" which are used by the package website in particular cases.

commitbf54eaef44c2d56064109bf5c4f7570dc7746ed2 authorEvan Czaplicki <evancz@users.noreply.github.com> dateMon 3 Jun 2019, 11:10 (7 years ago) parentd0415b4
1 file changed+73−43
compiler/src/Elm/Version.hs+73−43
compiler/src/Elm/Version.hs+73−43
@@ -1,3 +1,5 @@
1+{-# OPTIONS_GHC -Wall #-}
2+{-# LANGUAGE BangPatterns, UnboxedTuples #-}
13module Elm.Version
24 ( Version(..)
35 , one
@@ -7,10 +9,11 @@ module Elm.Version
79 , bumpMinor
810 , bumpMajor
911 , toChars
10− , toString
11− , fromString
12+ --
1213 , decoder
1314 , encode
15+ --
16+ , parser
1417 )
1518 where
1619
@@ -18,13 +21,15 @@ module Elm.Version
1821import Prelude hiding (max)
1922import Control.Monad (liftM3)
2023import Data.Binary (Binary, get, put, getWord8, putWord8)
21−import qualified Data.Utf8 as Utf8
2224import qualified Data.Version as Version
23−import Data.Word (Word16)
25+import Data.Word (Word8, Word16)
26+import Foreign.Ptr (Ptr, plusPtr, minusPtr)
2427import qualified Paths_elm
2528
2629import qualified Json.Decode as D
2730import qualified Json.Encode as E
31+import qualified Parse.Primitives as P
32+import Parse.Primitives (Row, Col)
2833
2934
3035
@@ -86,58 +91,26 @@ bumpMajor (Version major _minor _patch) =
8691
8792
8893
89−-- TO STRING
94+-- TO CHARS
9095
9196
92−toChars :: Version -> String
93−toChars vsn =
94− Utf8.toChars (toString vsn)
95−
96−
97−toString :: Version -> Utf8.String
98−toString (Version major minor patch) =
99− Utf8.join 0x2E {- . -}
100− [ Utf8.fromWord16 major
101− , Utf8.fromWord16 minor
102− , Utf8.fromWord16 patch
103− ]
104−
105−
106−
107−-- FROM STRING
108−
109−
110−fromString :: Utf8.String -> Maybe Version
111−fromString str =
112− case Utf8.split 0x2E {- . -} str of
113− [major, minor, patch] ->
114− Version
115− <$> Utf8.toWord16 major
116− <*> Utf8.toWord16 minor
117− <*> Utf8.toWord16 patch
118−
119− _ ->
120− Nothing
97+toChars :: Version -> [Char]
98+toChars (Version major minor patch) =
99+ show major ++ '.' : show minor ++ '.' : show patch
121100
122101
123102
124103-- JSON
125104
126105
127−decoder :: D.Decoder Utf8.String Version
106+decoder :: D.Decoder (Row, Col) Version
128107decoder =
129− do str <- D.string
130− case fromString str of
131− Just version ->
132− return version
133−
134− Nothing ->
135− D.failure str
108+ D.customString parser (,)
136109
137110
138111encode :: Version -> E.Value
139112encode version =
140− E.string (toString version)
113+ E.chars (toChars version)
141114
142115
143116
@@ -164,3 +137,60 @@ instance Binary Version where
164137 put major
165138 put minor
166139 put patch
140+
141+
142+
143+-- PARSER
144+
145+
146+parser :: P.Parser (Row, Col) Version
147+parser =
148+ do major <- numberParser
149+ P.word1 0x2E {-.-} (,)
150+ minor <- numberParser
151+ P.word1 0x2E {-.-} (,)
152+ patch <- numberParser
153+ return (Version major minor patch)
154+
155+
156+numberParser :: P.Parser (Row, Col) Word16
157+numberParser =
158+ P.Parser $ \(P.State src pos end indent row col) cok _ _ eerr ->
159+ if pos >= end then
160+ eerr row col (,)
161+ else
162+ let !word = P.unsafeIndex pos in
163+ if word == 0x30 {-0-} then
164+
165+ let
166+ !newState = P.State src (plusPtr pos 1) end indent row (col + 1)
167+ in
168+ cok 0 newState
169+
170+ else if isDigit word then
171+
172+ let
173+ (# total, newPos #) = chompWord16 (plusPtr pos 1) end (fromIntegral (word - 0x30))
174+ !newState = P.State src newPos end indent row (col + fromIntegral (minusPtr newPos pos))
175+ in
176+ cok total newState
177+
178+ else
179+ eerr row col (,)
180+
181+
182+chompWord16 :: Ptr Word8 -> Ptr Word8 -> Word16 -> (# Word16, Ptr Word8 #)
183+chompWord16 pos end total =
184+ if pos >= end then
185+ (# total, pos #)
186+ else
187+ let !word = P.unsafeIndex pos in
188+ if isDigit word then
189+ chompWord16 (plusPtr pos 1) end (10 * total + fromIntegral (word - 0x30))
190+ else
191+ (# total, pos #)
192+
193+
194+isDigit :: Word8 -> Bool
195+isDigit word =
196+ 0x30 {-0-} <= word && word <= 0x39 {-9-}