iocaine 2.2.0

The deadliest poison known to AI
Documentation
// SPDX-FileCopyrightText: 2025 Gergely Nagy
// SPDX-FileContributor: Gergely Nagy
//
// SPDX-License-Identifier: MIT

use roto::{Runtime, Val, roto_method, roto_static_method};
use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc;

use crate::means_of_production::{Error, MutableStringList};

#[derive(Debug, Clone, Default)]
pub struct Json(Rc<RefCell<serde_json::Value>>);

pub fn register_json(runtime: &mut Runtime) -> Result<(), Error> {
    runtime.register_clone_type_with_name::<Json>("Json", "A JSON value")?;

    {
        #[roto_static_method(runtime, Json)]
        fn load_file(path: Arc<str>) -> Val<Json> {
            let data = std::fs::read_to_string(path.as_ref()).unwrap_or_else(|e| {
                tracing::error!({ file = path.to_string() }, "Error loading JSON file: {e}");
                String::from("{}")
            });
            let json = serde_json::from_str(&data).unwrap_or_else(|e| {
                tracing::error!({ data }, "Error parsing JSON data: {e}");
                serde_json::from_str("{}").unwrap()
            });
            Json(Rc::new(RefCell::new(json))).into()
        }
    }

    #[roto_method(runtime, Json)]
    fn get_keys(json: Val<Json>) -> Val<MutableStringList> {
        match &*(*json).0.borrow() {
            serde_json::Value::Object(obj) => {
                MutableStringList(Rc::new(RefCell::new(obj.keys().cloned().collect())))
            }
            value => {
                tracing::warn!({ value = value.to_string() }, "JSON value is not an object");
                MutableStringList::default()
            }
        }
        .into()
    }

    Ok(())
}