pepl_stdlib/modules/
record.rs1use std::collections::BTreeMap;
6
7use crate::error::StdlibError;
8use crate::module::StdlibModule;
9use crate::value::Value;
10
11pub struct RecordModule;
13
14impl RecordModule {
15 pub fn new() -> Self {
16 Self
17 }
18}
19
20impl Default for RecordModule {
21 fn default() -> Self {
22 Self::new()
23 }
24}
25
26impl StdlibModule for RecordModule {
27 fn name(&self) -> &'static str {
28 "record"
29 }
30
31 fn has_function(&self, function: &str) -> bool {
32 matches!(function, "get" | "set" | "has" | "keys" | "values")
33 }
34
35 fn call(&self, function: &str, args: Vec<Value>) -> Result<Value, StdlibError> {
36 match function {
37 "get" => self.get(args),
38 "set" => self.set(args),
39 "has" => self.has(args),
40 "keys" => self.keys(args),
41 "values" => self.values(args),
42 _ => Err(StdlibError::unknown_function("record", function)),
43 }
44 }
45}
46
47impl RecordModule {
48 fn get(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
51 if args.len() != 2 {
52 return Err(StdlibError::wrong_args("record.get", 2, args.len()));
53 }
54 let fields = extract_record("record.get", &args[0], 1)?;
55 let key = extract_string("record.get", &args[1], 2)?;
56 Ok(fields.get(key).cloned().unwrap_or(Value::Nil))
57 }
58
59 fn set(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
62 if args.len() != 3 {
63 return Err(StdlibError::wrong_args("record.set", 3, args.len()));
64 }
65 let fields = extract_record("record.set", &args[0], 1)?;
66 let key = extract_string("record.set", &args[1], 2)?;
67 let mut new_fields = fields.clone();
68 new_fields.insert(key.to_string(), args[2].clone());
69 Ok(Value::record(new_fields))
70 }
71
72 fn has(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
74 if args.len() != 2 {
75 return Err(StdlibError::wrong_args("record.has", 2, args.len()));
76 }
77 let fields = extract_record("record.has", &args[0], 1)?;
78 let key = extract_string("record.has", &args[1], 2)?;
79 Ok(Value::Bool(fields.contains_key(key)))
80 }
81
82 fn keys(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
85 if args.len() != 1 {
86 return Err(StdlibError::wrong_args("record.keys", 1, args.len()));
87 }
88 let fields = extract_record("record.keys", &args[0], 1)?;
89 let keys: Vec<Value> = fields.keys().map(|k| Value::String(k.clone())).collect();
90 Ok(Value::List(keys))
91 }
92
93 fn values(&self, args: Vec<Value>) -> Result<Value, StdlibError> {
96 if args.len() != 1 {
97 return Err(StdlibError::wrong_args("record.values", 1, args.len()));
98 }
99 let fields = extract_record("record.values", &args[0], 1)?;
100 let values: Vec<Value> = fields.values().cloned().collect();
101 Ok(Value::List(values))
102 }
103}
104
105fn extract_record<'a>(
108 func: &str,
109 val: &'a Value,
110 pos: usize,
111) -> Result<&'a BTreeMap<String, Value>, StdlibError> {
112 match val {
113 Value::Record { fields, .. } => Ok(fields),
114 _ => Err(StdlibError::type_mismatch(
115 func,
116 pos,
117 "record",
118 val.type_name(),
119 )),
120 }
121}
122
123fn extract_string<'a>(func: &str, val: &'a Value, pos: usize) -> Result<&'a str, StdlibError> {
124 match val {
125 Value::String(s) => Ok(s),
126 _ => Err(StdlibError::type_mismatch(
127 func,
128 pos,
129 "string",
130 val.type_name(),
131 )),
132 }
133}