dg_xch_core 2.1.1

Core library containing type/error definitions, CLVM tools, Consensus and Pool definitions
Documentation
use crate::clvm::compile::tokenizer::{Token, TokenType, Tokenizer};
use crate::clvm::compile::{Constant, Function};
use std::borrow::Cow;
use std::fs;
use std::io::{Error, ErrorKind};
use std::path::Path;
use std::vec::IntoIter;

pub fn parse_function<'a>(
    conditions_queue: &mut IntoIter<Token<'a>>,
) -> Result<Function<'a>, Error> {
    let function_name = conditions_queue.next().ok_or(Error::new(
        ErrorKind::InvalidInput,
        "Unexpected End of Token Stream",
    ))?;
    assert_eq!(function_name.t_type, TokenType::Expression);
    assert_eq!(
        conditions_queue
            .next()
            .ok_or(Error::new(
                ErrorKind::InvalidInput,
                "Unexpected End of Token Stream"
            ))?
            .t_type,
        TokenType::StartCons
    );
    let mut function_args = vec![];
    loop {
        let arg_or_end = conditions_queue.next().ok_or(Error::new(
            ErrorKind::InvalidInput,
            "Unexpected End of Token Stream",
        ))?;
        match arg_or_end.t_type {
            TokenType::Expression => {
                function_args.push(arg_or_end);
            }
            TokenType::EndCons => {
                break;
            }
            _ => {
                return Err(Error::new(
                    ErrorKind::InvalidInput,
                    format!("Unexpected Token {arg_or_end:?}"),
                ))
            }
        }
    }
    Ok(Function {
        name: function_name,
        argument_names: function_args,
        function_body: conditions_queue.collect(),
    })
}

pub fn parse_constant<'a>(
    conditions_queue: &mut IntoIter<Token<'a>>,
) -> Result<Constant<'a>, Error> {
    let name = conditions_queue.next().ok_or(Error::new(
        ErrorKind::InvalidInput,
        "Unexpected End of Token Stream",
    ))?;
    if name.t_type != TokenType::Expression {
        return Err(Error::new(
            ErrorKind::InvalidInput,
            format!(
                "Unexpected Token, Expected Expression Got {:?}",
                name.t_type
            ),
        ));
    }
    let value = conditions_queue.next().ok_or(Error::new(
        ErrorKind::InvalidInput,
        "Unexpected End of Token Stream",
    ))?;
    if value.t_type != TokenType::Expression {
        return Err(Error::new(
            ErrorKind::InvalidInput,
            format!(
                "Unexpected Token, Expected Expression Got {:?}",
                value.t_type
            ),
        ));
    }
    let end_cons = conditions_queue.next().ok_or(Error::new(
        ErrorKind::InvalidInput,
        "Unexpected End of Token Stream",
    ))?;
    if end_cons.t_type != TokenType::EndCons {
        return Err(Error::new(
            ErrorKind::InvalidInput,
            format!(
                "Unexpected Token, Expected End Cons Got {:?}",
                end_cons.t_type
            ),
        ));
    }
    Ok(Constant { name, value })
}

pub fn parse_include<'a>(
    conditions_queue: &mut IntoIter<Token<'a>>,
    include_dirs: &[&str],
) -> Result<Tokenizer<'a>, Error> {
    let name_token = conditions_queue.next().ok_or(Error::new(
        ErrorKind::InvalidInput,
        "Unexpected End of Token Stream",
    ))?;
    if name_token.t_type != TokenType::Expression {
        Err(Error::new(
            ErrorKind::InvalidInput,
            format!(
                "Unexpected Token, Expected Expression Got {:?}",
                name_token.t_type
            ),
        ))
    } else {
        let file_name = String::from_utf8_lossy(&name_token.bytes);
        for include_dir in include_dirs {
            let path = Path::new(include_dir).join(file_name.as_ref());
            if path.exists() {
                let data = fs::read_to_string(&path).unwrap();
                return Ok(Tokenizer::new(Cow::Owned(data.trim().as_bytes().to_vec())));
            }
        }
        Err(Error::new(
            ErrorKind::NotFound,
            format!("Failed to Find include: {file_name}"),
        ))
    }
}