bytevectors.scm 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. ;;; Bytevectors
  2. ;;; Copyright (C) 2024 Igalia, S.L.
  3. ;;;
  4. ;;; Licensed under the Apache License, Version 2.0 (the "License");
  5. ;;; you may not use this file except in compliance with the License.
  6. ;;; You may obtain a copy of the License at
  7. ;;;
  8. ;;; http://www.apache.org/licenses/LICENSE-2.0
  9. ;;;
  10. ;;; Unless required by applicable law or agreed to in writing, software
  11. ;;; distributed under the License is distributed on an "AS IS" BASIS,
  12. ;;; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. ;;; See the License for the specific language governing permissions and
  14. ;;; limitations under the License.
  15. ;;; Commentary:
  16. ;;;
  17. ;;; Bytevectors.
  18. ;;;
  19. ;;; Code:
  20. (library (hoot bytevectors)
  21. (export make-bytevector
  22. bytevector-length
  23. bytevector-u8-ref
  24. bytevector-u8-set!
  25. bytevector-s8-ref
  26. bytevector-s8-set!
  27. bytevector-u16-native-ref
  28. bytevector-u16-native-set!
  29. bytevector-s16-native-ref
  30. bytevector-s16-native-set!
  31. bytevector-u32-native-ref
  32. bytevector-u32-native-set!
  33. bytevector-s32-native-ref
  34. bytevector-s32-native-set!
  35. bytevector-u64-native-ref
  36. bytevector-u64-native-set!
  37. bytevector-s64-native-ref
  38. bytevector-s64-native-set!
  39. bytevector-ieee-single-native-ref
  40. bytevector-ieee-single-native-set!
  41. bytevector-ieee-double-native-ref
  42. bytevector-ieee-double-native-set!
  43. bytevector?
  44. bytevector
  45. bytevector-concatenate
  46. bytevector-concatenate-reverse
  47. bytevector-append
  48. bytevector-copy
  49. bytevector-copy!)
  50. (import (rename (hoot primitives)
  51. (%< <)
  52. (%- -)
  53. (%+ +)
  54. (%null? null?)
  55. (%car car)
  56. (%cdr cdr))
  57. (hoot errors)
  58. (hoot match)
  59. (hoot bitwise))
  60. (define (1- x) (- x 1))
  61. (define (1+ x) (+ x 1))
  62. (define (bytevector? x) (%bytevector? x))
  63. (define (bytevector-length bv) (%bytevector-length bv))
  64. (define* (make-bytevector len #:optional (init 0))
  65. (check-size len (1- (ash 1 29)) 'make-bytevector)
  66. (check-range init -128 255 'make-bytevector)
  67. (%inline-wasm
  68. '(func (param $len i32) (param $init i32)
  69. (result (ref eq))
  70. (struct.new
  71. $mutable-bytevector
  72. (i32.const 0)
  73. (array.new $raw-bytevector (local.get $init) (local.get $len))))
  74. len init))
  75. (define (bytevector-u8-ref bv i) (%bytevector-u8-ref bv i))
  76. (define (bytevector-u8-set! bv i x) (%bytevector-u8-set! bv i x))
  77. (define (bytevector-s8-ref bv i) (%bytevector-s8-ref bv i))
  78. (define (bytevector-s8-set! bv i x) (%bytevector-s8-set! bv i x))
  79. (define (bytevector-u16-native-ref bv i) (%bytevector-u16-native-ref bv i))
  80. (define (bytevector-u16-native-set! bv i x) (%bytevector-u16-native-set! bv i x))
  81. (define (bytevector-s16-native-ref bv i) (%bytevector-s16-native-ref bv i))
  82. (define (bytevector-s16-native-set! bv i x) (%bytevector-s16-native-set! bv i x))
  83. (define (bytevector-u32-native-ref bv i) (%bytevector-u32-native-ref bv i))
  84. (define (bytevector-u32-native-set! bv i x) (%bytevector-u32-native-set! bv i x))
  85. (define (bytevector-s32-native-ref bv i) (%bytevector-s32-native-ref bv i))
  86. (define (bytevector-s32-native-set! bv i x) (%bytevector-s32-native-set! bv i x))
  87. (define (bytevector-u64-native-ref bv i) (%bytevector-u64-native-ref bv i))
  88. (define (bytevector-u64-native-set! bv i x) (%bytevector-u64-native-set! bv i x))
  89. (define (bytevector-s64-native-ref bv i) (%bytevector-s64-native-ref bv i))
  90. (define (bytevector-s64-native-set! bv i x) (%bytevector-s64-native-set! bv i x))
  91. (define (bytevector-ieee-single-native-ref bv i) (%bytevector-ieee-single-native-ref bv i))
  92. (define (bytevector-ieee-single-native-set! bv i x) (%bytevector-ieee-single-native-set! bv i x))
  93. (define (bytevector-ieee-double-native-ref bv i) (%bytevector-ieee-double-native-ref bv i))
  94. (define (bytevector-ieee-double-native-set! bv i x) (%bytevector-ieee-double-native-set! bv i x))
  95. (define (bytevector . inits)
  96. (define (length l)
  97. (let lp ((len 0) (l l))
  98. (if (null? l) len (lp (+ len 1) (cdr l)))))
  99. (let* ((len (length inits))
  100. (bv (make-bytevector len)))
  101. (let lp ((i 0) (inits inits))
  102. (when (< i len)
  103. (bytevector-u8-set! bv i (car inits))
  104. (lp (1+ i) (cdr inits))))
  105. bv))
  106. (define (bytevector-length* bv*)
  107. (let lp ((bv* bv*) (len 0))
  108. (match bv*
  109. (() len)
  110. ((bv . bv*) (lp bv* (+ len (bytevector-length bv)))))))
  111. (define (bytevector-concatenate bv*)
  112. (match bv*
  113. (() #vu8())
  114. ((bv) bv)
  115. (bv*
  116. (let* ((len (bytevector-length* bv*))
  117. (flattened (make-bytevector len 0)))
  118. (let lp ((bv* bv*) (cur 0))
  119. (match bv*
  120. (() flattened)
  121. ((bv . bv*)
  122. (bytevector-copy! flattened cur bv)
  123. (lp bv* (+ cur (bytevector-length bv))))))))))
  124. (define (bytevector-concatenate-reverse bv*)
  125. (match bv*
  126. (() #vu8())
  127. ((bv) bv)
  128. (bv*
  129. (let* ((len (bytevector-length* bv*))
  130. (flattened (make-bytevector len 0)))
  131. (let lp ((bv* bv*) (cur len))
  132. (match bv*
  133. (() flattened)
  134. ((bv . bv*)
  135. (let ((cur (- cur (bytevector-length bv))))
  136. (bytevector-copy! flattened cur bv)
  137. (lp bv* cur)))))))))
  138. (define (bytevector-append . args)
  139. (bytevector-concatenate args))
  140. (define* (bytevector-copy x #:optional (start 0) (end (bytevector-length x)))
  141. (check-type x bytevector? 'bytevector-copy)
  142. (check-range start 0 (bytevector-length x) 'bytevector-copy)
  143. (check-range end start (bytevector-length x) 'bytevector-copy)
  144. (%inline-wasm
  145. '(func (param $src (ref $bytevector)) (param $start i32) (param $end i32)
  146. (result (ref eq))
  147. (local $i0 i32)
  148. (local $vu0 (ref $raw-bytevector))
  149. (local.set $i0 (i32.sub (local.get $end) (local.get $start)))
  150. (local.set $vu0 (array.new_default $raw-bytevector (local.get $i0)))
  151. (array.copy $raw-bytevector $raw-bytevector
  152. (local.get $vu0) (i32.const 0)
  153. (struct.get $bytevector $vals (local.get $src))
  154. (local.get $start) (local.get $i0))
  155. (struct.new $bytevector (i32.const 0) (local.get $vu0)))
  156. x start end))
  157. (define* (bytevector-copy! to at from #:optional
  158. (start 0) (end (bytevector-length from)))
  159. ;; FIXME: check that `to` is mutable
  160. (check-type to bytevector? 'bytevector-copy!)
  161. (check-range at 0 (bytevector-length to) 'bytevector-copy!)
  162. (check-type from bytevector? 'bytevector-copy!)
  163. (check-range start 0 (bytevector-length from) 'bytevector-copy!)
  164. (check-range end start (bytevector-length from) 'bytevector-copy!)
  165. (%inline-wasm
  166. '(func (param $to (ref $mutable-bytevector)) (param $at i32)
  167. (param $from (ref $bytevector)) (param $start i32) (param $end i32)
  168. (array.copy $raw-bytevector $raw-bytevector
  169. (struct.get $mutable-bytevector $vals (local.get $to))
  170. (local.get $at)
  171. (struct.get $bytevector $vals (local.get $from))
  172. (local.get $start)
  173. (i32.sub (local.get $end) (local.get $start))))
  174. to at from start end)))