@@ -0,0 +1,268 @@
3+import Data.ByteArray as BA
8+-- Structure of the allocated ByteArray
9+-- [used_size][.....data.....]
10+-- used_size is an int and it takes up BA.bytesPerInt bytes
11+-- at the beginning of the array
18+ end : Int -- first offset not included in the array
25+dataOfs = 1 * BA.bytesPerInt
28+allocate : Int -> IO Bytes
29+allocate capacity = do
30+ arr <- BA.allocate (BA.bytesPerInt + capacity)
31+ BA.pokeInt 0 dataOfs arr
32+ BA.fill dataOfs capacity 0 arr -- zero the array
33+ return $ B arr dataOfs dataOfs
37+length (B arr ofs end) = end - ofs
41+empty = unsafePerformIO $ allocate minimalCapacity
45+null (B arr ofs end) = (ofs == end)
52+grow : Int -> Bytes -> IO Bytes
53+grow factor (B arr ofs end) = do
54+ maxUsed <- BA.peekInt 0 arr
55+ let bytesUsed = end - ofs
59+ else BA.size arr - ofs
60+ B arr' ofs' end' <- allocate $ (factor*bytesAvailable) `max` minimalCapacity
61+ BA.copy (arr, ofs) (arr', ofs') bytesUsed
62+ return $ B arr' ofs' (ofs' + bytesUsed)
66+snoc : Bytes -> Byte -> Bytes
67+snoc bs@(B arr ofs end) byte
68+ = if end >= BA.size arr
69+ then unsafePerformIO $ do -- need more space
71+ return $ snoc grown byte
72+ else unsafePerformIO $ do
73+ maxUsed <- BA.peekInt 0 arr
75+ then do -- someone already took the headroom, need copying
77+ return $ snoc copy byte
78+ else do -- can mutate
79+ BA.pokeInt 0 (end+1) arr
81+ return $ B arr ofs (end+1)
84+(|>) : Bytes -> Byte -> Bytes
88+ data SnocView : Type where
90+ Snoc : (bs : Bytes) -> (b : Byte) -> SnocView
93+ snocView : Bytes -> SnocView
94+ snocView (B arr ofs end) =
97+ else unsafePerformIO $ do
98+ last <- BA.peek (end-1) arr
99+ return $ SnocView.Snoc (B arr ofs (end-1)) last
102+ data ConsView : Type where
104+ Cons : (b : Byte) -> (bs : Bytes) -> ConsView
107+ consView : Bytes -> ConsView
108+ consView (B arr ofs end) =
111+ else unsafePerformIO $ do
112+ first <- BA.peek ofs arr
113+ return $ ConsView.Cons first (B arr (ofs+1) end)
118+(++) : Bytes -> Bytes -> Bytes
119+(++) bsL@(B arrL ofsL endL) bsR@(B arrR ofsR endR)
120+ = let countR = endR - ofsR in
121+ if endL + countR > BA.size arrL
122+ then unsafePerformIO $ do -- need more space
124+ return $ grown ++ bsR
125+ else unsafePerformIO $ do
126+ maxUsedL <- BA.peekInt 0 arrL
128+ then do -- headroom taken
130+ return $ copyL ++ bsR
131+ else do -- can mutate
132+ BA.pokeInt 0 (endL + countR) arrL
133+ BA.copy (arrR, ofsR) (arrL, endL) countR
134+ return $ B arrL ofsL (endL + countR)
136+dropPrefix : Int -> Bytes -> Bytes
137+dropPrefix n (B arr ofs end) = B arr (((ofs + n) `min` end) `max` dataOfs) end
139+takePrefix : Int -> Bytes -> Bytes
140+takePrefix n (B arr ofs end) = B arr ofs (((ofs + n) `min` end) `max` dataOfs)
142+pack : List Byte -> Bytes
143+pack = fromList empty
145+ fromList : Bytes -> List Byte -> Bytes
147+ fromList bs (x :: xs) = fromList (bs `snoc` x) xs
149+unpack : Bytes -> List Byte
150+unpack bs with (consView bs)
152+ | Cons x xs = x :: unpack (assert_smaller bs xs)
154+slice : Int -> Int -> Bytes -> Bytes
155+slice ofs' end' (B arr ofs end)
157+ (((ofs + ofs') `min` end) `max` dataOfs)
158+ (((ofs + end') `min` end) `max` dataOfs)
160+-- Folds with early exit.
161+-- If Bytes were a Functor, this would be equivalent
162+-- to a Traversable implementation interpreted in the Either monad.
163+data Result : Type -> Type where
164+ Stop : (result : a) -> Result a
165+ Cont : (acc : a) -> Result a
167+iterateR : (Byte -> a -> Result a) -> a -> Bytes -> a
168+iterateR f acc bs with (snocView bs)
170+ | Snoc ys y with (f y acc)
171+ | Stop result = result
172+ | Cont acc' = iterateR f acc' (assert_smaller bs ys)
174+iterateL : (a -> Byte -> Result a) -> a -> Bytes -> a
175+iterateL f acc bs with (consView bs)
177+ | Cons y ys with (f acc y)
178+ | Stop result = result
179+ | Cont acc' = iterateL f acc' (assert_smaller bs ys)
183+(.:) : (a -> b) -> (c -> d -> a) -> (c -> d -> b)
184+(.:) g f x y = g (f x y)
186+foldr : (Byte -> a -> a) -> a -> Bytes -> a
187+foldr f = iterateR (Cont .: f)
189+foldl : (a -> Byte -> a) -> a -> Bytes -> a
190+foldl f = iterateL (Cont .: f)
192+spanLength : (Byte -> Bool) -> Bytes -> Int
193+spanLength p = iterateL step 0
195+ step : Int -> Byte -> Result Int
197+ | True = Cont (1 + n)
200+find : Byte -> Bytes -> Maybe Int
201+find b (B arr ofs end) = unsafePerformIO $ BA.find b arr ofs end
203+splitAt : Int -> Bytes -> (Bytes, Bytes)
204+splitAt n bs = (takePrefix n bs, dropPrefix n bs)
206+splitOn : Byte -> Bytes -> (Bytes, Bytes)
207+splitOn b bs with (find b bs)
208+ | Nothing = (bs, empty)
209+ | Just ofs = (takePrefix ofs bs, dropPrefix (ofs+1) bs)
211+splitsOn : Byte -> Bytes -> List Bytes
212+splitsOn b bs with (find b bs)
214+ | Just ofs = takePrefix ofs bs :: splitsOn b (assert_smaller bs $ dropPrefix (ofs+1) bs)
216+asciiLines : Bytes -> List Bytes
217+asciiLines = splitsOn 0x0A
219+span : (Byte -> Bool) -> Bytes -> (Bytes, Bytes)
220+span p bs = splitAt (spanLength p bs) bs
222+break : (Byte -> Bool) -> Bytes -> (Bytes, Bytes)
223+break p bs = span (not . p) bs
226+cmp : Bytes -> Bytes -> Ordering
227+cmp (B arrL ofsL endL) (B arrR ofsR endR) = unsafePerformIO $ do
228+ let countL = endL - ofsL
229+ let countR = endR - ofsR
230+ let commonCount = countL `min` countR
231+ result <- BA.compare (arrL, ofsL) (arrR, ofsR) commonCount
235+ else compare countL countR
237+ i2o : Int -> Ordering
239+ i2o i = if i < 0 then LT else GT
241+implementation Eq Bytes where
242+ xs == ys = (Bytes.cmp xs ys == EQ)
244+implementation Ord Bytes where
247+toString : Bytes -> String
248+toString = foldr (strCons . chr . toInt) ""
250+fromString : String -> Bytes
251+fromString = foldl (\bs, c => bs |> fromInt (ord c)) empty . unpack
253+implementation Show Bytes where
254+ show = ("b" ++) . show . toString
256+implementation Semigroup Bytes where
259+implementation Monoid Bytes where
265+-- Build a ByteString on top of Bytes?
266+-- migrate to (Bits 8)?
268+-- bidirectional growth?