1use std::sync::{Arc, RwLock};
5
6use tan::{context::Context, error::Error, expr::Expr, util::module_util::require_module};
7
8pub fn buffer_new(args: &[Expr]) -> Result<Expr, Error> {
20 let [length] = args else {
23 return Err(Error::invalid_arguments("requires `length` argument", None));
24 };
25
26 let Some(length) = length.as_int() else {
28 return Err(Error::invalid_arguments(
29 &format!("length=`{length}` is not Int"),
30 length.range(),
31 ));
32 };
33
34 let length = length as usize;
35 let buf: Vec<u8> = vec![0; length];
37
38 Ok(Expr::Buffer(length, Arc::new(RwLock::new(buf))))
39}
40
41pub fn buffer_put(args: &[Expr]) -> Result<Expr, Error> {
43 let [buffer, index, value] = args else {
46 return Err(Error::invalid_arguments(
47 "requires `index` and `value` arguments",
48 None,
49 ));
50 };
51
52 let Some((length, mut buffer)) = buffer.as_buffer_mut() else {
53 return Err(Error::invalid_arguments(
54 &format!("buffer=`{buffer}` is not a Buffer"),
55 buffer.range(),
56 ));
57 };
58
59 let Some(i) = index.as_int() else {
60 return Err(Error::invalid_arguments(
61 &format!("index=`{index}` is not Int"),
62 index.range(),
63 ));
64 };
65
66 if i < 0 {
67 return Err(Error::invalid_arguments(
69 &format!("buffer index=`{i}` cannot be negative"),
70 index.range(),
71 ));
72 }
73
74 let i = i as usize;
75
76 if i >= length {
77 return Err(Error::invalid_arguments(
78 &format!("buffer index=`{i}` must be less than the buffer length=`{length}`"),
79 index.range(),
80 ));
81 }
82
83 let Some(value) = value.as_u8() else {
84 return Err(Error::invalid_arguments(
85 &format!("value=`{value}` is not U8"),
86 value.range(),
87 ));
88 };
89
90 buffer[i] = value;
91
92 Ok(Expr::None)
94}
95
96pub fn setup_lib_buffer(context: &mut Context) {
97 let module = require_module("prelude", context);
99
100 module.insert_invocable("Buffer", Expr::foreign_func(&buffer_new));
102
103 module.insert_invocable("put$$Buffer$$Int$$U8", Expr::foreign_func(&buffer_put));
106}
107
108