0 | module Data.ByteVect
  1 |
  2 | import Data.Maybe0
  3 | import Control.WellFounded
  4 | import Data.Buffer
  5 | import Data.Buffer.Builder
  6 | import Data.Buffer.Mutable
  7 | import Data.Nat.BSExtra
  8 |
  9 | import public Data.Buffer.Core
 10 | import public Data.Buffer.Indexed
 11 | import public Data.Byte
 12 |
 13 | %default total
 14 |
 15 | ||| An immutable, length-indexed byte vector.
 16 | |||
 17 | ||| Internally represented by a `Data.Buffer` together
 18 | ||| with its length and offset.
 19 | |||
 20 | ||| The internal buffer is treated as being immutable,
 21 | ||| so operations modifying a `ByteVect` will create
 22 | ||| and write to a new `Buffer`.
 23 | public export
 24 | data ByteVect : Nat -> Type where
 25 |   BV :  (buf    : IBuffer bufLen)
 26 |      -> (offset : Nat)
 27 |      -> (0 lte  : LTE (offset + len) bufLen)
 28 |      -> ByteVect len
 29 |
 30 | ||| Wrappes an immutable buffer in a `ByteVect`
 31 | export %inline
 32 | fromIBuffer : IBuffer n -> ByteVect n
 33 | fromIBuffer b = BV b 0 reflexive
 34 |
 35 | ||| Converts a `ByteVect n` to an `IBuffer n`.
 36 | |||
 37 | ||| In case the `ByteVect`'s inner offset is at zero, this just
 38 | ||| unwraps and returns then inner buffer (O(1)), otherwise the buffer's
 39 | ||| substring is copied to a new buffer (O(n)).
 40 | export
 41 | toIBuffer : {n : _} -> ByteVect n -> IBuffer n
 42 | toIBuffer (BV b 0 _) = take n b
 43 | toIBuffer (BV b o _) =
 44 |   run1 $ \t =>
 45 |    let mb # t := mbuffer1 n t
 46 |        _  # t := icopy b o 0 n mb t
 47 |     in unsafeFreeze mb t
 48 |
 49 | ||| An immutable string of raw bytes. For an length-indexed version,
 50 | ||| see module `ByteVect` and `Data.ByteVect`.
 51 | public export
 52 | record ByteString where
 53 |   constructor BS
 54 |   size : Nat
 55 |   repr : ByteVect size
 56 |
 57 | %inline
 58 | conv : {n : _} -> R1 rs (IBuffer n) -@ R1 rs ByteString
 59 | conv (v # t) = BS n (BV v 0 reflexive) # t
 60 |
 61 | ||| Safely wrap a mutable buffer in a `ByteString`.
 62 | export
 63 | freezeByteString : {n : _} -> WithMBuffer n ByteString
 64 | freezeByteString r t = conv $ freeze r t
 65 |
 66 | ||| Wrap a mutable buffer in a `ByteString` without copying.
 67 | |||
 68 | ||| Use this for reasons of efficiency when you are sure the buffer
 69 | ||| will not be shared otherwise.
 70 | export
 71 | unsafeFreezeByteString : {n : _} -> WithMBuffer n ByteString
 72 | unsafeFreezeByteString r t = conv $ unsafeFreeze r t
 73 |
 74 | ||| Safely wrap a mutable buffer in a `ByteString`.
 75 | export
 76 | freezeByteStringLTE : (m : Nat) -> (0 p : LTE m n) => WithMBuffer n ByteString
 77 | freezeByteStringLTE m r t = conv $ freezeLTE @{p} r m t
 78 |
 79 | ||| Wrap a mutable buffer in a `ByteString` without copying.
 80 | |||
 81 | ||| Use this for reasons of efficiency when you are sure the buffer
 82 | ||| will not be shared otherwise.
 83 | export
 84 | unsafeFreezeByteStringLTE : (m : Nat) -> (0 p : LTE m n) => WithMBuffer n ByteString
 85 | unsafeFreezeByteStringLTE m r t = conv $ unsafeFreezeLTE @{p} r m t
 86 |
 87 | ||| Reads the value of a `ByteVect` at the given position
 88 | export %inline
 89 | at : ByteVect n -> Fin n -> Bits8
 90 | at (BV buf o lte) x = atOffset buf x o
 91 |
 92 | ||| Safely access a value in an array at position `n - m`.
 93 | export %inline
 94 | ix : ByteVect n -> (0 m : Nat) -> {auto x: Ix (S m) n} -> Bits8
 95 | ix bv _ = at bv (ixToFin x)
 96 |
 97 | ||| Safely access a value in an array at the given position.
 98 | export %inline
 99 | atNat : ByteVect n -> (m : Nat) -> {auto 0 lt : LT m n} -> Bits8
100 | atNat bv x = at bv (natToFinLT x)
101 |
102 | export
103 | fromEnd : {n : _} -> ByteVect n -> (m : Nat) -> {auto 0 lt : LT m n} -> Bits8
104 | fromEnd bs m = atNat bs (n `minus` S m) @{minusLT _ _ lt}
105 |
106 | --------------------------------------------------------------------------------
107 | --          Making ByteStrings
108 | --------------------------------------------------------------------------------
109 |
110 | ||| The empty `ByteVect`.
111 | export
112 | empty : ByteVect 0
113 | empty = BV empty 0 %search
114 |
115 | ||| Converts a list of values to a `ByteVect` using
116 | ||| the given conversion function. O(n).
117 | export
118 | pack : (as : List Bits8) -> ByteVect (length as)
119 | pack as = BV (bufferL as) 0 reflexive
120 |
121 | ||| Converts a `String` to a `ByteVect`. Note: This will
122 | ||| correctly decode the corresponding UTF-8 string.
123 | export
124 | fromString : (s : String) -> ByteVect (cast $ stringByteLength s)
125 | fromString s = BV (fromString s) 0 reflexive
126 |
127 | ||| Converts a `ByteVect` to a UTF-8 encoded string
128 | export
129 | toString : {n : _} -> ByteVect n -> String
130 | toString (BV buf o _) = toString buf o n
131 |
132 | export %inline
133 | {n : _} -> Interpolation (ByteVect n) where interpolate = toString
134 |
135 | ||| Creates a `ByteVect` holding a single `Bits8` value.
136 | export %inline
137 | singleton : Bits8 -> ByteVect 1
138 | singleton v = pack [v]
139 |
140 | ||| Convert a `ByteVect` to a list of values using
141 | ||| the given conversion function.
142 | export
143 | toList : {n : _} -> (Bits8 -> a) -> ByteVect n -> List a
144 | toList f bs     = go Nil n
145 |
146 |   where
147 |     go : List a -> (x : Nat) -> (0 prf : LTE x n) => List a
148 |     go xs 0     = xs
149 |     go xs (S j) = go (f (atNat bs j) :: xs) j
150 |
151 | ||| Converts a `ByteVect` to a list of `Bits8` values. O(n).
152 | export %inline
153 | unpack : {n : _} -> ByteVect n -> List Bits8
154 | unpack = toList id
155 |
156 | ||| Converts a `ByteVect` to a String. All characters
157 | ||| will be in the range [0,255], so this does not perform
158 | ||| any character decoding.
159 | export %inline
160 | {n : Nat} -> Show (ByteVect n) where
161 |   showPrec p bs = showCon p "pack" (showArg $ toList id bs)
162 |
163 | --------------------------------------------------------------------------------
164 | --          Comparing ByteStrings
165 | --------------------------------------------------------------------------------
166 |
167 | ||| Lexicographic comparison of `ByteVect`s of distinct length
168 | export
169 | hcomp : {m,n : Nat} -> ByteVect m -> ByteVect n -> Ordering
170 | hcomp b1 b2 = go m n
171 |
172 |   where
173 |     go : (k,l : Nat) -> {auto a1 : Ix k m} -> {auto a2 : Ix l n} -> Ordering
174 |     go 0     0     = EQ
175 |     go 0     (S _) = LT
176 |     go (S _) 0     = GT
177 |     go (S k) (S j) = case compare (ix b1 k) (ix b2 j) of
178 |       EQ => go k j
179 |       r  => r
180 |
181 | ||| Heterogeneous equality for `ByteVect`s
182 | export
183 | heq : {m,n : Nat} -> ByteVect m -> ByteVect n -> Bool
184 | heq bs1 bs2 = hcomp bs1 bs2 == EQ
185 |
186 | export %inline
187 | {n : _} -> Eq (ByteVect n) where (==) = heq
188 |
189 | export %inline
190 | {n : _} -> Ord (ByteVect n) where compare = hcomp
191 |
192 | --------------------------------------------------------------------------------
193 | --          Core Functionality
194 | --------------------------------------------------------------------------------
195 |
196 | export
197 | generate : (n : Nat) -> (Fin n -> Bits8) -> ByteVect n
198 | generate n f = BV (generate n f) 0 refl
199 |
200 | export
201 | replicate : (n : Nat) -> Bits8 -> ByteVect n
202 | replicate n = generate n . const
203 |
204 | --------------------------------------------------------------------------------
205 | --          Concatenating ByteStrings
206 | --------------------------------------------------------------------------------
207 |
208 | ||| Concatenate two `ByteVect`s. O(n + m).
209 | export
210 | append : {m,n : _} -> ByteVect m -> ByteVect n -> ByteVect (m + n)
211 | append (BV src1 o1 lte1) (BV src2 o2 lte2) =
212 |   let buf := alloc (m+n) $ \r,t =>
213 |               let _ # t := icopy {n = m+n} src1 o1 0 m @{lte1} @{lteAddRight _} r t
214 |                   _ # t := icopy src2 o2 m n @{lte2} @{reflexive} r t
215 |                in unsafeFreeze r t
216 |    in BV buf 0 reflexive
217 |
218 | ||| Prepend a single `Bits8` to a `ByteVect`. O(n).
219 | export %inline
220 | cons : {n : _} -> Bits8 -> ByteVect n -> ByteVect (S n)
221 | cons = append . singleton
222 |
223 | ||| Append a single `Bits8` to a `ByteVect`. O(n).
224 | export %inline
225 | snoc : {n : _} -> Bits8 -> ByteVect n -> ByteVect (n + 1)
226 | snoc w bs = bs `append` singleton w
227 |
228 | --------------------------------------------------------------------------------
229 | --          Inspecting ByteStrings
230 | --------------------------------------------------------------------------------
231 |
232 | ||| Read the first element of a `ByteVect`. O(1).
233 | export
234 | head : ByteVect (S n) -> Bits8
235 | head bv = atNat bv 0
236 |
237 | ||| Drop the first `Bits8` from a `ByteVect`. O(1).
238 | export
239 | tail : ByteVect (S n) -> ByteVect n
240 | tail (BV buf o p) = BV buf (S o) (ltePlusSuccRight p)
241 |
242 | ||| Split the first `Bits8` from a `ByteVect`. O(1).
243 | export
244 | uncons : ByteVect (S n) -> (Bits8, ByteVect n)
245 | uncons bs = (head bs, tail bs)
246 |
247 | ||| Read the last `Bits8` from a `ByteVect`. O(1).
248 | export
249 | last : {n : _} -> ByteVect (S n) -> Bits8
250 | last bs = atNat bs n
251 |
252 | ||| Drop the last `Bits8` from a `ByteVect`. O(1).
253 | export
254 | init : ByteVect (S n) -> ByteVect n
255 | init (BV buf o p) = BV buf o (lteSuccLeft $ ltePlusSuccRight p)
256 |
257 | ||| Split a `ByteVect` at the last byte. O(1).
258 | export
259 | unsnoc : {n : _} -> ByteVect (S n) -> (Bits8, ByteVect n)
260 | unsnoc bs = (last bs, init bs)
261 |
262 | --------------------------------------------------------------------------------
263 | --          Mapping ByteStrings
264 | --------------------------------------------------------------------------------
265 |
266 | ||| Converts every `Bits8` in a `ByteVect` by applying the given
267 | ||| function. O(n).
268 | export
269 | map : {n : _} -> (Bits8 -> Bits8) -> ByteVect n -> ByteVect n
270 | map f bs = generate n (\x => f $ at bs x)
271 |
272 | ||| Interpreting the values stored in a `ByteVect` as 8 bit characters,
273 | ||| convert every lower-case character to its upper-case form. O(n)
274 | export %inline
275 | toUpper : {n : _} -> ByteVect n -> ByteVect n
276 | toUpper = map toUpper
277 |
278 | ||| Interpreting the values stored in a `ByteVect` as 8 bit characters,
279 | ||| convert every upper-case character to its lower-case form. O(n)
280 | export %inline
281 | toLower : {n : _} -> ByteVect n -> ByteVect n
282 | toLower = map toLower
283 |
284 | ||| Inverse the order of bytes in a `ByteVect`. O(n)
285 | export
286 | reverse : {n : _} -> ByteVect n -> ByteVect n
287 | reverse bs = generate n (\x => fromEnd bs (finToNat x) @{finToNatLT _})
288 |
289 | ||| True, if the predicate holds for all bytes
290 | ||| in the given `ByteVect`. O(n)
291 | export
292 | all : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> Bool
293 | all p bv = go n
294 |
295 |   where
296 |     go : (c : Nat) -> (x : Ix c n) => Bool
297 |     go 0     = True
298 |     go (S k) = if p (ix bv k) then go k else False
299 |
300 | ||| True, if the predicate holds for at least one byte
301 | ||| in the given `ByteVect`. O(n)
302 | export
303 | any : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> Bool
304 | any p bv = go n
305 |
306 |   where
307 |     go : (c : Nat) -> (x : Ix c n) => Bool
308 |     go 0     = False
309 |     go (S k) = if p (ix bv k) then True else go k
310 |
311 | ||| True, if the given `Bits8` appears in the `ByteVect`. O(n)
312 | export %inline
313 | elem : {n : _} -> Bits8 -> ByteVect n -> Bool
314 | elem b = any (b ==)
315 |
316 | ||| Fold a `ByteVect` from the left. O(n)
317 | export
318 | foldl : {n : _} -> (a -> Bits8 -> a) -> a -> ByteVect n -> a
319 | foldl f ini bv = go n ini
320 |
321 |   where
322 |     go : (c : Nat) -> (v : a) -> (x : Ix c n) => a
323 |     go 0     v = v
324 |     go (S k) v = go k (f v $ ix bv k)
325 |
326 | ||| Fold a `ByteVect` from the right. O(n)
327 | export
328 | foldr : {n : _} -> (Bits8 -> a -> a) -> a -> ByteVect n -> a
329 | foldr f ini bs = go n ini
330 |
331 |   where
332 |     go : (k : Nat) -> (v : a) -> (0 lt : LTE k n) => a
333 |     go 0     v = v
334 |     go (S k) v = go k (f (atNat bs k) v)
335 |
336 | ||| The `findIndex` function takes a predicate and a `ByteVect` and
337 | ||| returns the index of the first element in the ByteVect
338 | ||| satisfying the predicate. O(n)
339 | export
340 | findIndex : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> Maybe (Fin n)
341 | findIndex p bv = go n
342 |
343 |   where
344 |     go : (c : Nat) -> {auto x : Ix c n} -> Maybe (Fin n)
345 |     go 0     = Nothing
346 |     go (S k) = if p (ix bv k) then Just (ixToFin x) else go k
347 |
348 | ||| Return the index of the first occurence of the given
349 | ||| byte in the `ByteVect`, or `Nothing`, if the byte
350 | ||| does not appear in the ByteVect. O(n)
351 | export
352 | elemIndex : {n : _} -> Bits8 -> ByteVect n -> Maybe (Fin n)
353 | elemIndex c = findIndex (c ==)
354 |
355 | ||| Returns the first value byte in a `ByteVect` fulfilling
356 | ||| the given predicate. O(n)
357 | export
358 | find : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> Maybe Bits8
359 | find p bs = at bs <$> findIndex p bs
360 |
361 | export
362 | isPrefixOf : {m,n : _} -> ByteVect m -> ByteVect n -> Bool
363 | isPrefixOf bv1 bv2 = go m n
364 |
365 |   where
366 |     go : (c1,c2 : Nat) -> {auto _ : Ix c1 m} -> {auto _ : Ix c2 n} -> Bool
367 |     go 0     _     = True
368 |     go _     0     = False
369 |     go (S x) (S y) = if ix bv1 x == ix bv2 y then go x y else False
370 |
371 | export
372 | isSuffixOf : {m,n : _} -> ByteVect m -> ByteVect n -> Bool
373 | isSuffixOf bv1 bv2 = go m n
374 |
375 |   where
376 |     go : (o1,o2 : Nat) -> (0 _ : LTE o1 m) => (0 _ : LTE o2 n) => Bool
377 |     go 0     _     = True
378 |     go _     0     = False
379 |     go (S x) (S y) = if atNat bv1 x == atNat bv2 y then go x y else False
380 |
381 | --------------------------------------------------------------------------------
382 | --          Substrings
383 | --------------------------------------------------------------------------------
384 |
385 | findIndexOrLength : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> SubLength n
386 | findIndexOrLength p bv = go n
387 |
388 |   where
389 |     go : (c : Nat) -> {auto x : Ix c n} -> SubLength n
390 |     go 0     = fromIx x
391 |     go (S k) = if p (ix bv k) then fromIx x else go k
392 |
393 | findIndexOrLengthNL : {n : _} -> ByteVect n -> SubLength n
394 | findIndexOrLengthNL bv = go n
395 |
396 |   where
397 |     go : (c : Nat) -> {auto x : Ix c n} -> SubLength n
398 |     go 0     = fromIx x
399 |     go (S k) = case ix bv k of 10 => fromIx x_ => go k
400 |
401 | findFromEndUntil : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> SubLength n
402 | findFromEndUntil p bv = go n
403 |
404 |   where
405 |     go : (k : Nat) -> (0 lt : LTE k n) => SubLength n
406 |     go 0     = Element 0 LTEZero
407 |     go (S k) = if p (atNat bv k) then (Element (S k) lt) else go k
408 |
409 | 0 substrPrf : LTE (s + l) n -> LTE (o + n) n2 -> LTE ((o + s) + l) n2
410 | substrPrf p q =
411 |   let pp := rewrite sym (plusAssociative o s l) in ltePlusRight o p
412 |    in transitive pp q
413 |
414 | ||| Like `substr` for `String`, this extracts a substring
415 | ||| of the given `ByteVect` at the given start position
416 | ||| and of the given length. O(1).
417 | export %inline
418 | substring :
419 |      (start,length : Nat)
420 |   -> ByteVect n
421 |   -> {auto 0 inBounds : LTE (start + length) n}
422 |   -> ByteVect length
423 | -- inBounds : start + len       <= n
424 | -- p        : o + n             <= bufLen
425 | -- required : (o + start) + len <= bufLen
426 | substring start len (BV buf o p) =
427 |   BV buf (o + start) (substrPrf inBounds p)
428 |
429 | ||| Like `substring` but extracts a substring from position
430 | ||| `from` up to but not including position `till`.
431 | export
432 | substringFromTill :
433 |      (from, till : Nat)
434 |   -> {auto 0 lt1 : LTE from till}
435 |   -> {auto 0 lt2 : LTE till n}
436 |   -> ByteVect n
437 |   -> ByteVect (till `minus` from)
438 | substringFromTill f t bv =
439 |   substring f (t `minus` f) bv @{transitive (plusMinusLTE _ _ lt1) lt2}
440 |
441 | ||| Like `substring` but extracts a substring from position
442 | ||| `from` up to and including position `to`.
443 | export
444 | substringFromTo :
445 |      (from, to : Nat)
446 |   -> {auto 0 lte : LTE from to}
447 |   -> {auto 0 lt  : LT to n}
448 |   -> ByteVect n
449 |   -> ByteVect (S to `minus` from)
450 | substringFromTo f t bv = substringFromTill f (S t) bv
451 |
452 | export
453 | generateMaybe : (n : Nat) -> (Fin n -> Maybe Bits8) -> ByteString
454 | generateMaybe n f = alloc n (go n n)
455 |
456 |   where
457 |     go : (k,m : Nat) -> (x : Ix k n) => (y : Ix m n) => WithMBuffer n ByteString
458 |     go (S k) (S m) r t =
459 |       case f (ixToFin x) of
460 |         Nothing => go k (S m) r t
461 |         Just v  => let _ # t := setIx r m v t in go k m r t
462 |     go _ _ r t = unsafeFreezeByteStringLTE (ixToNat y) @{ixLTE y} r t
463 |
464 | export
465 | mapMaybe : {n : _} -> (Bits8 -> Maybe Bits8) -> ByteVect n -> ByteString
466 | mapMaybe f bv = generateMaybe n (f . at bv)
467 |
468 | export
469 | filter : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> ByteString
470 | filter p = mapMaybe (\b => if p b then Just b else Nothing)
471 |
472 | ||| Return a `ByteVect` with the first `n` values of
473 | ||| the input string. O(1)
474 | export
475 | take : (0 k : Nat) -> (0 lt : LTE k n) => ByteVect n -> ByteVect k
476 | take k (BV buf o p) =
477 |   -- p        : o + n <= bufLen
478 |   -- lt       : k     <= n
479 |   -- required : o + k <= bufLen
480 |   BV buf o (transitive (ltePlusRight o lt) p)
481 |
482 | ||| Return a `ByteVect` with the last `n` values of
483 | ||| the input string. O(1)
484 | export
485 | takeEnd :
486 |      {n : _}
487 |   -> (k : Nat)
488 |   -> {auto 0 lt : LTE k n}
489 |   -> ByteVect n
490 |   -> ByteVect k
491 | takeEnd k (BV buf o p) =
492 |   -- p        : o + n             <= bufLen
493 |   -- lt       : k                 <= n
494 |   -- required : ((o + n) - k) + k <= bufLen
495 |   let 0 q := plusMinus' k (o + n) (lteAddLeft o lt)
496 |    in BV buf ((o + n) `minus` k) (rewrite q in p)
497 |
498 | ||| Remove the first `n` values from a `ByteVect`. O(1)
499 | export
500 | drop : (k : Nat) -> (0 lt : LTE k n) => ByteVect n -> ByteVect (n `minus` k)
501 | drop k (BV buf o p) =
502 |   -- p        : o + n             <= bufLen
503 |   -- lt       : k                 <= n
504 |   -- required : (o + k) + (n - k) <= bufLen
505 |   let 0 q := cong (o +) (plusMinus k n lt)
506 |       0 r := plusAssociative o k (n `minus` k)
507 |    in BV buf (o + k) (rewrite (trans (sym r) q) in p)
508 |
509 | ||| Remove the last `n` values from a `ByteVect`. O(1)
510 | export
511 | dropEnd :
512 |      (0 k : Nat)
513 |   -> {auto 0 lt : LTE k n}
514 |   -> ByteVect n
515 |   -> ByteVect (n `minus` k)
516 | dropEnd k (BV buf o p) =
517 |   -- p        : o + n       <= bufLen
518 |   -- lt       : k           <= n
519 |   -- required : o + (n - k) <= bufLen
520 |   BV buf o (transitive (ltePlusRight o $ minusLTE n k) p)
521 |
522 | export
523 | splitAt :
524 |      {n : _}
525 |   -> (k : Nat)
526 |   -> {auto 0 lte : LTE k n}
527 |   -> ByteVect n
528 |   -> (ByteVect k, ByteVect (n `minus` k))
529 | splitAt k bs = (take k bs, drop k bs)
530 |
531 | ||| Extracts the longest prefix of elements satisfying the
532 | ||| predicate.
533 | export
534 | takeWhile : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> ByteString
535 | takeWhile p bs =
536 |   let Element k _ = findIndexOrLength (not . p) bs
537 |    in BS k $ take k bs
538 |
539 | ||| Returns the longest (possibly empty) suffix of elements
540 | ||| satisfying the predicate.
541 | export
542 | takeWhileEnd : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> ByteString
543 | takeWhileEnd f bs =
544 |   let Element k _ = findFromEndUntil (not . f) bs
545 |    in BS _ $ drop k bs
546 |
547 | ||| Drops the longest (possibly empty) prefix of elements
548 | ||| satisfying the predicate and returns the remainder.
549 | export
550 | dropWhile : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> ByteString
551 | dropWhile f bs =
552 |   let Element k _ = findIndexOrLength (not . f) bs
553 |    in BS _ $ drop k bs
554 |
555 | ||| Drops the longest (possibly empty) suffix of elements
556 | ||| satisfying the predicate and returns the remainder.
557 | export
558 | dropWhileEnd : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> ByteString
559 | dropWhileEnd f bs =
560 |   let Element k _ = findFromEndUntil (not . f) bs
561 |    in BS k $ take k bs
562 |
563 | ||| Remove leading whitespace from a `ByteString`
564 | export
565 | trimLeft : {n : _} -> ByteVect n -> ByteString
566 | trimLeft = dropWhile isSpace
567 |
568 | ||| Remove trailing whitespace from a `ByteString`
569 | export
570 | trimRight : {n : _} -> ByteVect n -> ByteString
571 | trimRight = dropWhileEnd isSpace
572 |
573 | ||| Remove all leading and trailing whitespace from a `ByteString`
574 | export
575 | trim : {n : _} -> ByteVect n -> ByteString
576 | trim bs = let BS k bs' := trimLeft bs in trimRight bs'
577 |
578 | public export
579 | record BreakRes (n : Nat) where
580 |   constructor MkBreakRes
581 |   lenFst : Nat
582 |   lenSnd : Nat
583 |   fst    : ByteVect lenFst
584 |   snd    : ByteVect lenSnd
585 |   0 prf  : LTE (lenFst + lenSnd) n
586 |
587 | export
588 | breakRes : {n : _} -> ByteVect n -> SubLength n -> BreakRes n
589 | breakRes bs (Element k p) =
590 |   let bs1 := take k bs
591 |       bs2 := drop k bs
592 |    in MkBreakRes k (n `minus` k) bs1 bs2 (plusMinusLTE k n p)
593 |
594 | ||| Returns the longest (possibly empty) prefix of elements which do not
595 | ||| satisfy the predicate and the remainder of the string.
596 | export %inline
597 | break : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> BreakRes n
598 | break p bs = breakRes bs (findIndexOrLength p bs)
599 |
600 | ||| Returns the longest (possibly empty) prefix before the first newline character
601 | export %inline
602 | breakNL : {n : _} -> ByteVect n -> BreakRes n
603 | breakNL bs = breakRes bs (findIndexOrLengthNL bs)
604 |
605 | ||| Returns the longest (possibly empty) suffix of elements which do not
606 | ||| satisfy the predicate and the remainder of the string.
607 | export %inline
608 | breakEnd : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> BreakRes n
609 | breakEnd  p bs = breakRes bs (findFromEndUntil p bs)
610 |
611 | ||| Returns the longest (possibly empty) prefix of elements
612 | ||| satisfying the predicate and the remainder of the string.
613 | export %inline
614 | span : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> BreakRes n
615 | span p = break (not . p)
616 |
617 | ||| Returns the longest (possibly empty) suffix of elements
618 | ||| satisfying the predicate and the remainder of the string.
619 | export %inline
620 | spanEnd : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> BreakRes n
621 | spanEnd p bs = breakRes bs (findFromEndUntil (not . p) bs)
622 |
623 | ||| Returns the index where the given substring occurs in the
624 | ||| given bytevector for the first time
625 | export
626 | substringIndex : {k,n : _} -> ByteVect k -> ByteVect n -> SubLength n
627 | substringIndex sep bv = go n
628 |
629 |   where
630 |     go : (c : Nat) -> {auto x : Ix c n} -> SubLength n
631 |     go 0     = fromIx x
632 |     go (S k) =
633 |       if isPrefixOf sep (drop (ixToNat x) @{ixLTE x} bv) then fromIx x else go k
634 |
635 | ||| Returns the longest (possibly empty) prefix of a
636 | ||| byte vector that does not contain the given substring
637 | ||| plus the remainder of the byte vector.
638 | export %inline
639 | breakAtSubstring : {k,n : _} -> ByteVect k -> ByteVect n -> BreakRes n
640 | breakAtSubstring sep bs = breakRes bs (substringIndex sep bs)
641 |
642 | ||| Splits a 'ByteVect' into components delimited by
643 | ||| separators, where the predicate returns True for a separator element.
644 | ||| The resulting components do not contain the separators. Two adjacent
645 | ||| separators result in an empty component in the output. eg.
646 | export
647 | splitWith : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> List ByteString
648 | splitWith p bs = go Lin n bs (sizeAccessible n)
649 |
650 |   where
651 |     go :
652 |          SnocList ByteString
653 |       -> (m : Nat)
654 |       -> ByteVect m
655 |       -> (0 acc : SizeAccessible m)
656 |       -> List ByteString
657 |     go sb m bs' (Access rec) = case break p bs' of
658 |       MkBreakRes l1 0      b1 _  p => sb <>> [BS l1 b1]
659 |       MkBreakRes l1 (S l2) b1 b2 p =>
660 |         go (sb :< BS l1 b1) l2 (tail b2) (rec l2 $ ltPlusSuccRight' _ p)
661 |
662 | ||| Like `splitWith`, but removes empty components.
663 | export
664 | splitWithNonEmpty : {n : _} -> (Bits8 -> Bool) -> ByteVect n -> List ByteString
665 | splitWithNonEmpty p = filter ((/= Z) . size) . splitWith p
666 |
667 | ||| Break a `ByteVect` into pieces separated by the byte
668 | ||| argument, consuming the delimiter.
669 | |||
670 | ||| As for all splitting functions in this library, this function does
671 | ||| not copy the substrings, it just constructs new `ByteString`s that
672 | ||| are slices of the original.
673 | export %inline
674 | split : {n : _} -> Bits8 -> ByteVect n -> List ByteString
675 | split b = splitWith (b ==)
676 |
677 | ||| Like `split`, but removes empty components.
678 | export
679 | splitNonEmpty : {n : _} -> Bits8 -> ByteVect n -> List ByteString
680 | splitNonEmpty p = filter ((/= Z) . size) . split p
681 |
682 | export
683 | lines : {n : _} -> ByteVect n -> List ByteString
684 | lines bs = go Lin n bs (sizeAccessible n)
685 |
686 |   where
687 |     go :
688 |          SnocList ByteString
689 |       -> (m : Nat)
690 |       -> ByteVect m
691 |       -> (0 acc : SizeAccessible m)
692 |       -> List ByteString
693 |     go sb m bs' (Access rec) = case breakNL bs' of
694 |       MkBreakRes l1 0      b1 _  p => sb <>> [BS l1 b1]
695 |       MkBreakRes l1 (S l2) b1 b2 p =>
696 |         go (sb :< BS l1 b1) l2 (tail b2) (rec l2 $ ltPlusSuccRight' _ p)
697 |
698 | 0 blocksLemma1 : (m,n : Nat) -> LT (S n `minus` S m) (S n)
699 | blocksLemma1 m n = LTESucc $ minusLTE _ _
700 |
701 | 0 blocksLemma2 : (m,n : Nat) -> LTE (S k) n -> LT (n `minus` S m) n
702 | blocksLemma2 m (S _) (LTESucc _) = blocksLemma1 m _
703 |
704 | ||| Splits the second byte vector whenever the first called
705 | ||| `sep` occurs.
706 | |||
707 | ||| The bytestrings in the result no longer contain `sep` as
708 | ||| a substring.
709 | |||
710 | ||| Note: If `sep` is the empty byte vector, `[BS n val]` is returned
711 | |||       as the result.
712 | export
713 | splitAtSubstring :
714 |      {k,n : _}
715 |   -> (sep : ByteVect k)
716 |   -> (val : ByteVect n)
717 |   -> List ByteString
718 | splitAtSubstring {k = 0}   sep bv = [BS _ bv]
719 | splitAtSubstring {k = S m} sep bv = go [<] bv (sizeAccessible n)
720 |   where
721 |     go : {o : _}
722 |       -> SnocList ByteString
723 |       -> (body  : ByteVect o)
724 |       -> (0 acc : SizeAccessible o)
725 |       -> List ByteString
726 |     go sb body (Access rec) =
727 |       let MkBreakRes l1 l2 b1 b2 p1 := breakAtSubstring sep body
728 |        in case tryLTE {n = l2} (S m) of
729 |             Nothing0 => sb <>> [BS l1 b1]
730 |             Just0 p2  =>
731 |               let 0 p3 := lteAddLeft {m = l2} l1 reflexive
732 |                   0 p4 := blocksLemma2 m l2 p2
733 |                   0 p5 := transitive (transitive p4 p3) p1
734 |                in go (sb :< BS l1 b1) (drop (S m) b2) (rec _ p5)
735 |
736 | export
737 | isInfixOf : {m,n : _} -> ByteVect m -> ByteVect n -> Bool
738 | isInfixOf bv1 bv2 = m == 0 || go n
739 |
740 |   where
741 |     go : (c : Nat) -> (x : Ix c n) => Bool
742 |     go 0     = False
743 |     go (S k) = isPrefixOf bv1 (drop (ixToNat x) @{ixLTE x} bv2) || go k
744 |
745 | --------------------------------------------------------------------------------
746 | --          Parsing Numbers
747 | --------------------------------------------------------------------------------
748 |
749 | ||| Parse a natural number in the given base.
750 | export
751 | parseAnyNat :
752 |      {n : _}
753 |   -> (base : Nat)
754 |   -> {auto 0 p1 : LTE 2 base}
755 |   -> {auto 0 p2 : LTE base 16}
756 |   -> ByteVect n
757 |   -> Maybe Nat
758 | parseAnyNat {n = Z} _    bv = Nothing
759 | parseAnyNat         base bv = go n 0
760 |
761 |   where
762 |     go : (c,res : Nat) -> (x : Ix c n) => Maybe Nat
763 |     go 0     res = Just res
764 |     go (S k) res =
765 |       let Just n := fromHexDigit $ ix bv k | Nothing => Nothing
766 |        in if n < base then go k (res * base + n) else Nothing
767 |
768 | ||| Parses a natural number in decimal notation.
769 | export %inline
770 | parseDecimalNat : {n : _} -> ByteVect n -> Maybe Nat
771 | parseDecimalNat {n = Z} bv = Nothing
772 | parseDecimalNat         bv = go n 0
773 |
774 |   where
775 |     go : (c,res : Nat) -> (x : Ix c n) => Maybe Nat
776 |     go 0     res = Just res
777 |     go (S k) res =
778 |       let Just n := fromDigit $ ix bv k | Nothing => Nothing
779 |        in go k (res * 10 + n)
780 |
781 | export %inline
782 | parseHexadecimalNat : {n : _} -> ByteVect n -> Maybe Nat
783 | parseHexadecimalNat = parseAnyNat 10
784 |
785 | export %inline
786 | parseOctalNat : {n : _} -> ByteVect n -> Maybe Nat
787 | parseOctalNat = parseAnyNat 8
788 |
789 | export %inline
790 | parseBinaryNat : {n : _} -> ByteVect n -> Maybe Nat
791 | parseBinaryNat = parseAnyNat 2
792 |
793 | export
794 | parseInteger : {n : _} -> ByteVect n -> Maybe Integer
795 | parseInteger {n = Z}   _  = Nothing
796 | parseInteger {n = S _} bv = case head bv of
797 |   43 => cast          <$> parseDecimalNat (tail bv) -- '+'
798 |   45 => negate . cast <$> parseDecimalNat (tail bv) -- '-'
799 |   _  => cast <$> parseDecimalNat bv
800 |
801 |
802 | -- parsing Double
803 |
804 | isE : Bits8 -> Bool
805 | isE 69  = True
806 | isE 101 = True
807 | isE _   = False
808 |
809 | fract : {n : _} -> ByteVect n -> Maybe Double
810 | fract bv =
811 |   let Just k := parseDecimalNat bv | Nothing => Nothing
812 |    in Just (cast k / (pow 10 $ cast n))
813 |
814 | exp : {n : _} -> ByteVect n -> Maybe Double
815 | exp bv =
816 |   let Just exp := parseInteger bv | Nothing => Nothing
817 |    in Just $ pow 10.0 (cast exp)
818 |
819 | parseDotted : {n : _} -> ByteVect n -> Maybe Double
820 | parseDotted bv = go 0 0 n
821 |   where
822 |     go : (v,exp,c : Nat) -> (x : Ix c n) => Maybe Double
823 |     go v exp 0     = case exp of
824 |       0 => Just $ cast v
825 |       _ => Just $ cast v / cast exp
826 |     go v exp (S k) =
827 |       case ix bv k of
828 |         48 => go (v * 10 + 0) (exp * 10) k
829 |         49 => go (v * 10 + 1) (exp * 10) k
830 |         50 => go (v * 10 + 2) (exp * 10) k
831 |         51 => go (v * 10 + 3) (exp * 10) k
832 |         52 => go (v * 10 + 4) (exp * 10) k
833 |         53 => go (v * 10 + 5) (exp * 10) k
834 |         54 => go (v * 10 + 6) (exp * 10) k
835 |         55 => go (v * 10 + 7) (exp * 10) k
836 |         56 => go (v * 10 + 8) (exp * 10) k
837 |         57 => go (v * 10 + 9) (exp * 10) k
838 |         46 => case exp of
839 |           0 => go v 1 k
840 |           _ => Nothing
841 |         _  => Nothing
842 |
843 | parsePosDbl : {n : _} -> ByteVect n -> Maybe Double
844 | parsePosDbl bv = case parseDotted bv of
845 |   Just v  => Just v
846 |   Nothing => case break isE bv of
847 |     MkBreakRes lf (S _) dotStr expStr _ =>
848 |       let Just fract := parseDotted dotStr | Nothing => Nothing
849 |           Just e     := exp (tail expStr)  | Nothing => Nothing
850 |        in Just $ fract * e
851 |     MkBreakRes _ 0 _ _ _ => Nothing
852 |
853 | export
854 | parseDouble : {n : _} -> ByteVect n -> Maybe Double
855 | parseDouble {n = Z}   _  = Nothing
856 | parseDouble {n = S _} bv = case head bv of
857 |   43 => parsePosDbl (tail bv)             -- '+'
858 |   45 => negate  <$> parsePosDbl (tail bv) -- '-'
859 |   _  => parsePosDbl bv
860 |
861 | --------------------------------------------------------------------------------
862 | -- Using Builders
863 | --------------------------------------------------------------------------------
864 |
865 | export %inline
866 | putByteVect : Builder q => {n : _} -> ByteVect n -> F1' q
867 | putByteVect (BV buf off _) = putBytesFrom off n buf
868 |