| /- | |
| Copyright (c) 2019 Microsoft Corporation. All rights reserved. | |
| Released under Apache 2.0 license as described in the file LICENSE. | |
| Author: Leonardo de Moura | |
| -/ | |
| prelude | |
| import Init.Data.Array.Basic | |
| import Init.Data.Array.Subarray | |
| import Init.Data.UInt | |
| import Init.Data.Option.Basic | |
| universes u | |
| structure ByteArray where | |
| data : Array UInt8 | |
| attribute [extern "lean_byte_array_mk"] ByteArray.mk | |
| attribute [extern "lean_byte_array_data"] ByteArray.data | |
| namespace ByteArray | |
| @[extern "lean_mk_empty_byte_array"] | |
| def mkEmpty (c : @& Nat) : ByteArray := | |
| { data := #[] } | |
| def empty : ByteArray := mkEmpty 0 | |
| instance : Inhabited ByteArray := ⟨empty⟩ | |
| @[extern "lean_byte_array_push"] | |
| def push : ByteArray → UInt8 → ByteArray | |
| | ⟨bs⟩, b => ⟨bs.push b⟩ | |
| @[extern "lean_byte_array_size"] | |
| def size : (@& ByteArray) → Nat | |
| | ⟨bs⟩ => bs.size | |
| @[extern "lean_byte_array_get"] | |
| def get! : (@& ByteArray) → (@& Nat) → UInt8 | |
| | ⟨bs⟩, i => bs.get! i | |
| @[extern "lean_byte_array_set"] | |
| def set! : ByteArray → (@& Nat) → UInt8 → ByteArray | |
| | ⟨bs⟩, i, b => ⟨bs.set! i b⟩ | |
| def isEmpty (s : ByteArray) : Bool := | |
| s.size == 0 | |
| /-- | |
| Copy the slice at `[srcOff, srcOff + len)` in `src` to `[destOff, destOff + len)` in `dest`, growing `dest` if necessary. | |
| If `exact` is `false`, the capacity will be doubled when grown. -/ | |
| @[extern "lean_byte_array_copy_slice"] | |
| def copySlice (src : @& ByteArray) (srcOff : Nat) (dest : ByteArray) (destOff len : Nat) (exact : Bool := true) : ByteArray := | |
| ⟨dest.data.extract 0 destOff ++ src.data.extract srcOff len ++ dest.data.extract (destOff + len) dest.data.size⟩ | |
| def extract (a : ByteArray) (b e : Nat) : ByteArray := | |
| a.copySlice b empty 0 (e - b) | |
| protected def append (a : ByteArray) (b : ByteArray) : ByteArray := | |
| -- we assume that `append`s may be repeated, so use asymptotic growing; use `copySlice` directly to customize | |
| b.copySlice 0 a a.size b.size false | |
| instance : Append ByteArray := ⟨ByteArray.append⟩ | |
| partial def toList (bs : ByteArray) : List UInt8 := | |
| let rec loop (i : Nat) (r : List UInt8) := | |
| if i < bs.size then | |
| loop (i+1) (bs.get! i :: r) | |
| else | |
| r.reverse | |
| loop 0 [] | |
| @[inline] partial def findIdx? (a : ByteArray) (p : UInt8 → Bool) (start := 0) : Option Nat := | |
| let rec @[specialize] loop (i : Nat) := | |
| if i < a.size then | |
| if p (a.get! i) then some i else loop (i+1) | |
| else | |
| none | |
| loop start | |
| end ByteArray | |
| def List.toByteArray (bs : List UInt8) : ByteArray := | |
| let rec loop | |
| | [], r => r | |
| | b::bs, r => loop bs (r.push b) | |
| loop bs ByteArray.empty | |
| instance : ToString ByteArray := ⟨fun bs => bs.toList.toString⟩ |