(.using [library [lux (.except) ["[0]" ffi] [abstract [equivalence (.only Equivalence)] [monoid (.only Monoid)]] [control ["[0]" try (.only Try)] ["[0]" exception (.only exception:)]] [data [text ["%" format]] [collection ["[0]" array [\\unsafe (.only)]]]] [math [number ["n" nat]]]]] ["[0]" / ["[1]" \\unsafe]]) (type: .public Binary /.Binary) (def: .public size (-> Binary Nat) (|>> /.size)) (def: .public empty (-> Nat Binary) (|>> /.empty)) (def: .public (mix $ init it) (All (_ a) (-> (-> I64 a a) a Binary a)) (let [size (/.size it)] (loop (again [index 0 output init]) (if (n.< size index) (again (++ index) ($ (/.bits_8 index it) output)) output)))) (exception: .public (index_out_of_bounds [size Nat index Nat]) (exception.report "Size" (%.nat size) "Index" (%.nat index))) (with_template [ ] [(def: .public ( index it) (-> Nat Binary (Try I64)) (if (n.< (/.size it) (|> index )) {try.#Success ( index it)} (exception.except ..index_out_of_bounds [(/.size it) index])))] [bits_8 /.bits_8 (|>)] [bits_16 /.bits_16 (n.+ 1)] [bits_32 /.bits_32 (n.+ 3)] [bits_64 /.bits_64 (n.+ 7)] ) (with_template [ ] [(def: .public ( index value it) (-> Nat (I64 Any) Binary (Try Binary)) (if (n.< (/.size it) (|> index )) {try.#Success ( index value it)} (exception.except ..index_out_of_bounds [(/.size it) index])))] [has_8! /.has_8! (|>)] [has_16! /.has_16! (n.+ 1)] [has_32! /.has_32! (n.+ 3)] [has_64! /.has_64! (n.+ 7)] ) (def: .public equivalence (Equivalence Binary) (implementation (def: (= reference sample) (/.= reference sample)))) (exception: .public (cannot_copy [bytes Nat source_input Nat target_output Nat]) (exception.report "Bytes" (%.nat bytes) "Source input space" (%.nat source_input) "Target output space" (%.nat target_output))) (def: .public (copy! bytes source_offset source target_offset target) (-> Nat Nat Binary Nat Binary (Try Binary)) (let [source_input (n.- source_offset (/.size source)) target_output (n.- target_offset (/.size target))] (if (or (n.< bytes source_input) (n.< bytes target_output)) (exception.except ..cannot_copy [bytes source_input target_output]) {try.#Success (/.copy! bytes source_offset source target_offset target)}))) (exception: .public (slice_out_of_bounds [size Nat offset Nat length Nat]) (exception.report "Size" (%.nat size) "Offset" (%.nat offset) "Length" (%.nat length))) (def: .public (slice offset length binary) (-> Nat Nat Binary (Try Binary)) (let [size (/.size binary) limit (n.+ length offset)] (if (n.< limit size) (exception.except ..slice_out_of_bounds [size offset length]) {try.#Success (/.slice offset length binary)}))) (def: .public (after bytes binary) (-> Nat Binary Binary) (cond (n.= 0 bytes) binary (n.< (/.size binary) bytes) (/.slice bytes (n.- bytes (/.size binary)) binary) ... else (/.empty 0))) (def: .public monoid (Monoid Binary) (implementation (def: identity (/.empty 0)) (def: (composite left right) (let [sizeL (/.size left) sizeR (/.size right) output (/.empty (n.+ sizeL sizeR))] (exec (/.copy! sizeL 0 left 0 output) (/.copy! sizeR 0 right sizeL output) output)))))