0 | module Core.Binary.Prims
2 | import Core.Context.Context
6 | import Data.List.Elem
11 | import Libraries.Data.NatSet
12 | import Libraries.Data.PosMap
13 | import public Libraries.Utils.Binary
14 | import public Libraries.Utils.String
15 | import Libraries.Data.WithDefault
22 | data Bin : Type where
26 | data ResID : Type where
29 | interface TTC a where
31 | toBuf : Ref Bin Binary => a -> Core ()
34 | fromBuf : Ref Bin Binary => Core a
38 | initBinary : Core (Ref Bin Binary)
40 | = do Just buf <- coreLift $
newBuffer blockSize
41 | | Nothing => throw (InternalError "Buffer creation failed")
42 | newRef Bin (newBinary buf (cast blockSize))
45 | initBinaryS : Int -> Core (Ref Bin Binary)
47 | = do Just buf <- coreLift $
newBuffer s
48 | | Nothing => throw (InternalError "Buffer creation failed")
49 | newRef Bin (newBinary buf (cast s))
51 | extendBinary : Integer -> Binary -> Core Binary
52 | extendBinary need (MkBin buf l s u)
53 | = do let newsize = s * 2
54 | let s' = if (newsize - l) < need
57 | Just buf' <- coreLift $
resizeBuffer buf (cast s')
58 | | Nothing => throw (InternalError "Buffer expansion failed")
59 | pure (MkBin buf' l s' u)
62 | corrupt : String -> Core a
63 | corrupt ty = throw (TTCError (Corrupt ty))
68 | tag : {auto b : Ref Bin Binary} -> Int -> Core ()
70 | = do chunk <- get Bin
73 | do coreLift $
setBits8 (buf chunk) (cast $
loc chunk) $
cast val
74 | put Bin (appended 1 chunk)
75 | else do chunk' <- extendBinary 1 chunk
76 | coreLift $
setBits8 (buf chunk') (cast $
loc chunk') $
cast val
77 | put Bin (appended 1 chunk')
80 | getTag : {auto b : Ref Bin Binary} -> Core Int
82 | = do chunk <- get Bin
83 | if toRead chunk >= 1
85 | do val <- coreLift $
getBits8 (buf chunk) (cast $
loc chunk)
86 | put Bin (incLoc 1 chunk)
88 | else throw (TTCError (EndOfBuffer "Bits8"))
96 | [Wasteful] TTC Int where
98 | = do chunk <- get Bin
101 | do coreLift $
setInt (buf chunk) (cast $
loc chunk) val
102 | put Bin (appended 8 chunk)
103 | else do chunk' <- extendBinary 8 chunk
104 | coreLift $
setInt (buf chunk') (cast $
loc chunk') val
105 | put Bin (appended 8 chunk')
108 | = do chunk <- get Bin
109 | if toRead chunk >= 8
111 | do val <- coreLift $
getInt (buf chunk) (cast $
loc chunk)
112 | put Bin (incLoc 8 chunk)
114 | else throw (TTCError (EndOfBuffer ("Int " ++ show (loc chunk, Binary.size chunk))))
119 | = if val >= -
127 && val < 128
120 | then tag (val + 127)
123 | if avail chunk >= 8
125 | do coreLift $
setInt (buf chunk) (cast $
loc chunk) val
126 | put Bin (appended 8 chunk)
127 | else do chunk' <- extendBinary 8 chunk
128 | coreLift $
setInt (buf chunk') (cast $
loc chunk') val
129 | put Bin (appended 8 chunk')
133 | 255 => do chunk <- get Bin
134 | if toRead chunk >= 8
136 | do val <- coreLift $
getInt (buf chunk) (cast $
loc chunk)
137 | put Bin (incLoc 8 chunk)
139 | else throw (TTCError (EndOfBuffer ("Int " ++ show (loc chunk, Binary.size chunk))))
140 | t => pure (t - 127)
147 | = do let ireq = stringByteLength val
148 | let req : Integer = cast ireq
151 | if avail chunk >= req
153 | do coreLift $
setString (buf chunk) (cast $
loc chunk) val
154 | put Bin (appended req chunk)
155 | else do chunk' <- extendBinary req chunk
156 | coreLift $
setString (buf chunk') (cast $
loc chunk') val
157 | put Bin (appended req chunk')
160 | = do ilen <- fromBuf {a = Int}
162 | let len = cast ilen
163 | when (len < 0) $
corrupt "String"
164 | if toRead chunk >= len
166 | do val <- coreLift $
getString (buf chunk) (cast $
loc chunk) ilen
167 | put Bin (incLoc len chunk)
169 | else throw (TTCError (EndOfBuffer ("String length " ++ show len ++
170 | " at " ++ show (loc chunk))))
175 | = do let len = used val
176 | let ilen : Int = cast len
179 | if avail chunk >= len
181 | do coreLift $
copyData (buf val) 0 ilen
182 | (buf chunk) (cast $
loc chunk)
183 | put Bin (appended len chunk)
184 | else do chunk' <- extendBinary len chunk
185 | coreLift $
copyData (buf val) 0 ilen
186 | (buf chunk') (cast $
loc chunk')
187 | put Bin (appended len chunk')
190 | = do ilen <- fromBuf
191 | let len : Integer = cast ilen
193 | if toRead chunk >= len
195 | do Just newbuf <- coreLift $
newBuffer ilen
196 | | Nothing => corrupt "Binary"
197 | coreLift $
copyData (buf chunk) (cast $
loc chunk) ilen
199 | put Bin (incLoc len chunk)
200 | pure (MkBin newbuf 0 len len)
201 | else throw (TTCError (EndOfBuffer "Binary"))
205 | toBuf False = tag 0
211 | _ => corrupt "Bool"
215 | toBuf c = toBuf (cast {to=Int} c)
218 | pure (cast {from=Int} i)
223 | = do chunk <- get Bin
224 | if avail chunk >= 8
226 | do coreLift $
setDouble (buf chunk) (cast $
loc chunk) val
227 | put Bin (appended 8 chunk)
228 | else do chunk' <- extendBinary 8 chunk
229 | coreLift $
setDouble (buf chunk') (cast $
loc chunk') val
230 | put Bin (appended 8 chunk')
233 | = do chunk <- get Bin
234 | if toRead chunk >= 8
236 | do val <- coreLift $
getDouble (buf chunk) (cast $
loc chunk)
237 | put Bin (incLoc 8 chunk)
239 | else throw (TTCError (EndOfBuffer "Double"))
242 | (TTC a, TTC b) => TTC (a, b) where
257 | (TTC a, {y : a} -> TTC (p y)) => TTC (DPair a p) where
268 | TTC a => TTC (Maybe a) where
278 | 1 => do val <- fromBuf
280 | _ => corrupt "Maybe"
283 | TTC a => TTC (WithDefault a def) where
284 | toBuf def = onWithDefault
292 | 0 => pure defaulted
293 | 1 => do val <- fromBuf
294 | pure (specified val)
295 | _ => corrupt "WithDefault"
298 | (TTC a, TTC b) => TTC (Either a b) where
308 | 0 => do val <- fromBuf
310 | 1 => do val <- fromBuf
312 | _ => corrupt "Either"
315 | TTC a => TTC (List a) where
317 | = do toBuf (TailRec_length xs)
318 | traverse_ (toBuf) xs
323 | length_aux : List a -> Int -> Int
324 | length_aux [] len = len
325 | length_aux (_::xs) len = length_aux xs (1 + len)
327 | TailRec_length : List a -> Int
328 | TailRec_length xs = length_aux xs 0
331 | = do len <- fromBuf {a = Int}
332 | readElems [] (integerToNat (cast len))
334 | readElems : List a -> Nat -> Core (List a)
335 | readElems xs Z = pure (reverse xs)
337 | = do val <- fromBuf
338 | readElems (val :: xs) k
341 | TTC a => TTC (List1 a) where
343 | = do toBuf (head xxs)
352 | {n : Nat} -> TTC a => TTC (Vect n a) where
353 | toBuf xs = writeAll xs
355 | writeAll : forall n . Vect n a -> Core ()
356 | writeAll [] = pure ()
357 | writeAll (x :: xs) = do toBuf x;
writeAll xs
359 | fromBuf {n} = rewrite sym (plusZeroRightNeutral n) in readElems [] n
361 | readElems : Vect done a -> (todo : Nat) -> Core (Vect (todo + done) a)
362 | readElems {done} xs Z
363 | = pure (reverse xs)
364 | readElems {done} xs (S k)
365 | = do val <- fromBuf
366 | rewrite (plusSuccRightSucc k done)
367 | readElems (val :: xs) k
370 | (TTC a, Measure a) => TTC (PosMap a) where
371 | toBuf = toBuf . toList
372 | fromBuf = fromList <$> fromBuf
374 | %hide Fin.fromInteger
376 | count : List.Elem.Elem x xs -> Int
378 | count (There p) = 1 + count p
380 | toLimbs : Integer -> List Int
384 | else if x == -
1 then [-
1]
385 | else fromInteger (prim__and_Integer x 0xffffffff) ::
386 | toLimbs (prim__shr_Integer x 32)
388 | fromLimbs : List Int -> Integer
390 | fromLimbs (x :: xs) = cast x + prim__shl_Integer (fromLimbs xs) 32
395 | = assert_total $
if val < 0
397 | toBuf (toLimbs (-val))
399 | toBuf (toLimbs val)
403 | 0 => do val <- fromBuf
404 | pure (-(fromLimbs val))
405 | 1 => do val <- fromBuf
406 | pure (fromLimbs val)
407 | _ => corrupt "Integer"
411 | toBuf x = toBuf $
cast {to = Int} x
412 | fromBuf = cast {from = Int} <$> fromBuf
416 | toBuf x = toBuf $
cast {to = Int} x
417 | fromBuf = cast {from = Int} <$> fromBuf
421 | toBuf x = toBuf $
cast {to = Integer} x
422 | fromBuf = cast {from = Integer} <$> fromBuf
426 | toBuf x = toBuf $
cast {to = Integer} x
427 | fromBuf = cast {from = Integer} <$> fromBuf
431 | toBuf x = toBuf $
cast {to = Int} x
432 | fromBuf = cast {from = Int} <$> fromBuf
436 | toBuf x = toBuf $
cast {to = Int} x
437 | fromBuf = cast {from = Int} <$> fromBuf
441 | toBuf x = toBuf $
cast {to = Int} x
442 | fromBuf = cast {from = Int} <$> fromBuf
446 | toBuf x = toBuf $
cast {to = Integer} x
447 | fromBuf = cast {from = Integer} <$> fromBuf
451 | toBuf val = toBuf (cast {to=Integer} val)
453 | = do val <- fromBuf
454 | pure (fromInteger val)
458 | toBuf ns = toBuf (cast {to=Integer} ns)
459 | fromBuf = cast {from=Integer} <$> fromBuf
463 | modTime : String -> Core Timestamp
465 | = do Right f <- coreLift $
openFile fname Read
466 | | Left err => pure $
MkTimestamp 0 0
467 | Right t <- coreLift $
fileTime f
468 | | Left err => do coreLift $
closeFile f
469 | pure $
MkTimestamp 0 0
470 | coreLift $
closeFile f
474 | hashFileWith : Maybe String -> String -> Core (Maybe String)
475 | hashFileWith Nothing _ = pure Nothing
476 | hashFileWith (Just sha256sum) fileName
477 | = do Right fileHandle <- coreLift $
popen
478 | (sha256sum ++ " \"" ++ osEscape fileName ++ "\"") Read
480 | Right hashLine <- coreLift $
fGetLine fileHandle
482 | do ignore $
coreLift $
pclose fileHandle
484 | ignore $
coreLift $
pclose fileHandle
485 | let w@(_::_) = words hashLine
487 | pure $
Just $
last w
490 | err = coreFail $
InternalError ("Can't get " ++ sha256sum ++ " of " ++ fileName)
491 | osEscape : String -> String
492 | osEscape = if isWindows
494 | else escapeStringUnix
497 | TTC a => TTC (SnocList a) where
499 | = do toBuf (TailRec_length xs)
505 | length_aux : SnocList a -> Int -> Int
506 | length_aux [<] len = len
507 | length_aux (xs :< _) len = length_aux xs (1 + len)
509 | TailRec_length : SnocList a -> Int
510 | TailRec_length xs = length_aux xs 0
513 | = do len <- fromBuf {a = Int}
514 | readElems [<] (integerToNat (cast len))
516 | readElems : SnocList a -> Nat -> Core (SnocList a)
517 | readElems xs Z = pure (reverse xs)
519 | = do val <- fromBuf
520 | readElems (xs :< val) k