wp-lang 0.2.2

WPL language crate with AST, parser, evaluator, builtins, and generators.
Documentation
use wp_model_core::raw::RawData;
use wp_parse_api::{WparseError, WparseReason, WparseResult};

use super::raw_to_utf8_string;

#[derive(Debug)]
pub struct JsonLikeProc;

pub(crate) fn is_json_like_text(input: &str) -> bool {
    let sample = input.trim_start_matches(|ch: char| ch.is_whitespace() || ch == '\u{feff}');
    let Some(first) = sample.chars().next() else {
        return false;
    };

    match first {
        '{' => sample.contains(':') && sample.contains('"'),
        '[' => sample.contains(',') || sample.contains(']') || sample.contains('{'),
        _ => false,
    }
}

impl wp_parse_api::PipeProcessor for JsonLikeProc {
    fn process(&self, data: RawData) -> WparseResult<RawData> {
        if is_json_like_text(&raw_to_utf8_string(&data)) {
            Ok(data)
        } else {
            Err(WparseError::from(WparseReason::NotMatch))
        }
    }

    fn name(&self) -> &'static str {
        "json_like"
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::parser::error::WplCodeResult;
    use wp_parse_api::PipeProcessor;

    const UNKNOWN_JSON_SAMPLE: &str = include_str!("../../../tests/unknow.json");

    use crate::parser::error::IntoWplCodeError;
    #[test]
    fn json_like_matches_valid_and_broken_json_objects() {
        assert!(is_json_like_text(r#"{"a":1}"#));
        assert!(is_json_like_text(UNKNOWN_JSON_SAMPLE));
    }

    #[test]
    fn json_like_rejects_plain_text() {
        assert!(!is_json_like_text("hello world"));
        assert!(!is_json_like_text("  2026-03-31 plain log"));
    }

    #[test]
    fn json_like_pipe_preserves_input() -> WplCodeResult<()> {
        let raw = RawData::from_string(UNKNOWN_JSON_SAMPLE.to_string());
        let out = JsonLikeProc.process(raw).map_err(|e| e.into_wpl_err())?;
        assert_eq!(raw_to_utf8_string(&out), UNKNOWN_JSON_SAMPLE);
        Ok(())
    }

    #[test]
    fn json_like_pipe_returns_not_match_for_plain_text() {
        let raw = RawData::from_string("plain-text".to_string());
        let err = JsonLikeProc
            .process(raw)
            .expect_err("plain text should not match");
        assert_eq!(*err.reason(), WparseReason::NotMatch);
    }
}