use crate::error::Error;
use crate::slab::ParseSlab;
use std::str::{from_utf8, from_utf8_unchecked};
use std::ptr;
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct ExpressionI(pub usize);
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct ValueI(pub usize);
#[derive(Debug, PartialEq)]
pub struct Expression {
pub(crate) first: Value,
pub(crate) pairs: Vec<ExprPair>,
}
#[derive(Debug, PartialEq)]
pub(crate) struct ExprPair(pub BinaryOp, pub Value);
#[derive(Debug, PartialEq)]
pub enum Value {
EConstant(f64),
EUnaryOp(UnaryOp),
EStdFunc(StdFunc),
EPrintFunc(PrintFunc),
}
use Value::{EConstant, EUnaryOp, EStdFunc, EPrintFunc};
#[derive(Debug, PartialEq)]
pub enum UnaryOp {
EPos(ValueI),
ENeg(ValueI),
ENot(ValueI),
EParentheses(ExpressionI),
}
use UnaryOp::{EPos, ENeg, ENot, EParentheses};
#[derive(Debug, PartialEq, PartialOrd, Copy, Clone)]
pub enum BinaryOp {
EOR = 1,
EAND = 2,
ENE = 3,
EEQ = 4,
EGTE = 5,
ELTE = 6,
EGT = 7,
ELT = 8,
EAdd = 9,
ESub = 10,
EMul = 11,
EDiv = 12,
EMod = 13,
EExp = 14,
}
use BinaryOp::{EAdd, ESub, EMul, EDiv, EMod, EExp, ELT, ELTE, EEQ, ENE, EGTE, EGT, EOR, EAND};
#[derive(Debug, PartialEq)]
pub enum StdFunc {
EVar(String),
#[cfg(feature="unsafe-vars")]
EUnsafeVar{name:String, ptr:*const f64},
EFunc{name:String, args:Vec<ExpressionI>},
EFuncInt(ExpressionI),
EFuncCeil(ExpressionI),
EFuncFloor(ExpressionI),
EFuncAbs(ExpressionI),
EFuncSign(ExpressionI),
EFuncLog{ base:Option<ExpressionI>, expr:ExpressionI},
EFuncRound{modulus:Option<ExpressionI>, expr:ExpressionI},
EFuncMin{first:ExpressionI, rest:Vec<ExpressionI>},
EFuncMax{first:ExpressionI, rest:Vec<ExpressionI>},
EFuncE,
EFuncPi,
EFuncSin(ExpressionI),
EFuncCos(ExpressionI),
EFuncTan(ExpressionI),
EFuncASin(ExpressionI),
EFuncACos(ExpressionI),
EFuncATan(ExpressionI),
EFuncSinH(ExpressionI),
EFuncCosH(ExpressionI),
EFuncTanH(ExpressionI),
EFuncASinH(ExpressionI),
EFuncACosH(ExpressionI),
EFuncATanH(ExpressionI),
}
use StdFunc::{EVar, EFunc, EFuncInt, EFuncCeil, EFuncFloor, EFuncAbs, EFuncSign, EFuncLog, EFuncRound, EFuncMin, EFuncMax, EFuncE, EFuncPi, EFuncSin, EFuncCos, EFuncTan, EFuncASin, EFuncACos, EFuncATan, EFuncSinH, EFuncCosH, EFuncTanH, EFuncASinH, EFuncACosH, EFuncATanH};
#[cfg(feature="unsafe-vars")]
use StdFunc::EUnsafeVar;
#[derive(Debug, PartialEq)]
pub struct PrintFunc(pub Vec<ExpressionOrString>);
#[derive(Debug, PartialEq)]
pub enum ExpressionOrString {
EExpr(ExpressionI),
EStr(String),
}
use ExpressionOrString::{EExpr, EStr};
impl Clone for PrintFunc {
fn clone(&self) -> Self {
let mut vec = Vec::<ExpressionOrString>::with_capacity(self.0.len());
for x_or_s in self.0.iter() {
vec.push(match x_or_s {
EExpr(i) => EExpr(*i),
EStr(s) => EStr(s.clone()),
});
}
PrintFunc(vec)
}
}
enum Token<T> {
Pass,
Bite(T),
}
use Token::{Pass, Bite};
macro_rules! peek {
($bs:ident) => {
$bs.first().copied()
};
}
macro_rules! peek_n {
($bs:ident, $skip:literal) => {
$bs.get($skip).copied()
};
($bs:ident, $skip:ident) => {
$bs.get($skip).copied()
};
($bs:ident, $skip:expr) => {
$bs.get($skip).copied()
};
}
macro_rules! peek_is {
($bs:ident, $skip:literal, $val:literal) => {
peek_n!($bs,$skip) == Some($val)
};
($bs:ident, $skip:expr, $val:literal) => {
peek_n!($bs,$skip) == Some($val)
};
}
macro_rules! read {
($bs:ident) => {
match $bs.first() {
Some(b) => {
*$bs = &$bs[1..];
Ok(*b)
}
None => Err(Error::EOF),
}
};
($bs:ident, $parsing:literal) => {
match $bs.first() {
Some(b) => {
*$bs = &$bs[1..];
Ok(*b)
}
None => Err(Error::EofWhileParsing($parsing.to_string())),
}
};
}
macro_rules! skip {
($bs:ident) => {
*$bs = &$bs[1..];
};
}
macro_rules! skip_n {
($bs:ident, $n:literal) => {
*$bs = &$bs[$n..];
};
($bs:ident, $n:ident) => {
*$bs = &$bs[$n..];
};
}
macro_rules! is_space {
($b:ident) => {
if $b>b' ' { false }
else {
$b==b' ' || $b==b'\n' || $b==b'\t' || $b==b'\r'
}
};
}
macro_rules! spaces {
($bs:ident) => {
while let Some(b) = peek!($bs) {
if !is_space!(b) { break }
skip!($bs);
}
};
}
pub const DEFAULT_EXPR_LEN_LIMIT : usize = 4096;
pub const DEFAULT_EXPR_DEPTH_LIMIT: usize = 32;
pub struct Parser {
pub expr_len_limit :usize,
pub expr_depth_limit:usize,
}
impl Parser {
#[inline]
pub const fn new() -> Self { Self{expr_len_limit:DEFAULT_EXPR_LEN_LIMIT,
expr_depth_limit:DEFAULT_EXPR_DEPTH_LIMIT} }
fn is_varname_byte(b:u8, i:usize) -> bool {
(b'A'<=b && b<=b'Z') || (b'a'<=b && b<=b'z') || b==b'_' || (i>0 && ( b'0'<=b && b<=b'9' ))
}
fn is_varname_byte_opt(bo:Option<u8>, i:usize) -> bool {
match bo {
Some(b) => Self::is_varname_byte(b,i),
None => false,
}
}
#[inline]
pub fn parse(&self, expr_str:&str, slab:&mut ParseSlab) -> Result<ExpressionI,Error> {
slab.clear();
self.parse_noclear(expr_str, slab)
}
#[inline]
pub fn parse_noclear(&self, expr_str:&str, slab:&mut ParseSlab) -> Result<ExpressionI,Error> {
if expr_str.len()>self.expr_len_limit { return Err(Error::TooLong); }
let mut bs = expr_str.as_bytes();
self.read_expression(slab, &mut bs, 0, true)
}
fn read_expression(&self, slab:&mut ParseSlab, bs:&mut &[u8], depth:usize, expect_eof:bool) -> Result<ExpressionI,Error> {
if depth>self.expr_depth_limit { return Err(Error::TooDeep); }
let first = self.read_value(slab,bs,depth)?;
let mut pairs = Vec::<ExprPair>::with_capacity(8);
loop {
match self.read_binaryop(bs)? {
Pass => break,
Bite(bop) => {
let val = self.read_value(slab,bs,depth)?;
pairs.push(ExprPair(bop,val));
}
}
}
spaces!(bs);
if expect_eof && !bs.is_empty() {
let bs_str = match from_utf8(bs) {
Ok(s) => s,
Err(..) => "Utf8Error while handling UnparsedTokensRemaining error",
};
return Err(Error::UnparsedTokensRemaining(bs_str.to_string()));
}
Ok(slab.push_expr(Expression{first, pairs})?)
}
fn read_value(&self, slab:&mut ParseSlab, bs:&mut &[u8], depth:usize) -> Result<Value,Error> {
if depth>self.expr_depth_limit { return Err(Error::TooDeep) }
match Self::read_const(slab,bs)? {
Pass => {}
Bite(c) => return Ok(EConstant(c)),
}
match self.read_unaryop(slab,bs,depth)? {
Pass => {}
Bite(u) => return Ok(EUnaryOp(u)),
}
match self.read_callable(slab,bs,depth)? {
Pass => {}
Bite(c) => return Ok(c),
}
if bs.is_empty() { return Err(Error::EofWhileParsing("value".to_string())); }
Err(Error::InvalidValue)
}
fn read_const(slab:&mut ParseSlab, bs:&mut &[u8]) -> Result<Token<f64>,Error> {
spaces!(bs);
let mut toklen=0; let mut sign_ok=true; let mut specials_ok=true; let mut suffix_ok=true; let mut saw_val=false;
loop {
match peek_n!(bs, toklen) {
None => break,
Some(b) => {
if b'0'<=b && b<=b'9' || b==b'.' {
saw_val = true;
sign_ok=false; specials_ok=false;
toklen = toklen+1;
} else if sign_ok && (b==b'-' || b==b'+') {
sign_ok = false;
toklen = toklen+1;
} else if saw_val && (b==b'e' || b==b'E') {
suffix_ok = false;
sign_ok = true;
toklen = toklen+1;
} else if specials_ok && ( b==b'N' && peek_is!(bs,toklen+1,b'a') && peek_is!(bs,toklen+2,b'N') || b==b'i' && peek_is!(bs,toklen+1,b'n') && peek_is!(bs,toklen+2,b'f') ) {
#[cfg(feature="alpha-keywords")]
{
saw_val = true;
suffix_ok = false;
toklen = toklen+3;
}
break;
} else {
break;
}
}
}
}
if !saw_val { return Ok(Pass); }
let mut tok = unsafe { from_utf8_unchecked(&bs[..toklen]) };
if suffix_ok {
match peek_n!(bs,toklen) {
None => (),
Some(b) => {
let (exp,suffixlen) = match b {
b'k' | b'K' => (3,1),
b'M' => (6,1),
b'G' => (9,1),
b'T' => (12,1),
b'm' => (-3,1),
b'u' | b'\xb5' => (-6,1),
b'\xc2' if peek_is!(bs,toklen+1,b'\xb5') => (-6,2),
b'n' => (-9,1),
b'p' => (-12,1),
_ => (0,0),
};
if exp!=0 {
slab.char_buf.clear();
slab.char_buf.push_str(tok);
slab.char_buf.push('e');
slab.char_buf.push_str(&exp.to_string());
tok = &slab.char_buf;
toklen = toklen+suffixlen;
}
}
}
}
let val = tok.parse::<f64>().map_err(|_| { Error::ParseF64(tok.to_string()) })?;
skip_n!(bs,toklen);
Ok(Bite(val))
}
fn read_unaryop(&self, slab:&mut ParseSlab, bs:&mut &[u8], depth:usize) -> Result<Token<UnaryOp>,Error> {
spaces!(bs);
match peek!(bs) {
None => Ok(Pass),
Some(b) => match b {
b'+' => {
skip!(bs);
let v = self.read_value(slab,bs,depth+1)?;
Ok(Bite(EPos(slab.push_val(v)?)))
}
b'-' => {
skip!(bs);
let v = self.read_value(slab,bs,depth+1)?;
Ok(Bite(ENeg(slab.push_val(v)?)))
}
b'(' => {
skip!(bs);
let xi = self.read_expression(slab,bs,depth+1,false)?;
spaces!(bs);
if read!(bs,"parentheses")? != b')' { return Err(Error::Expected(")".to_string())); }
Ok(Bite(EParentheses(xi)))
}
b'[' => {
skip!(bs);
let xi = self.read_expression(slab,bs,depth+1,false)?;
spaces!(bs);
if read!(bs,"square brackets")? != b']' { return Err(Error::Expected("]".to_string())); }
Ok(Bite(EParentheses(xi)))
}
b'!' => {
skip!(bs);
let v = self.read_value(slab,bs,depth+1)?;
Ok(Bite(ENot(slab.push_val(v)?)))
}
_ => Ok(Pass),
}
}
}
fn read_binaryop(&self, bs:&mut &[u8]) -> Result<Token<BinaryOp>,Error> {
spaces!(bs);
match peek!(bs) {
None => Ok(Pass),
Some(b) => match b {
b'+' => { skip!(bs); Ok(Bite(EAdd)) }
b'-' => { skip!(bs); Ok(Bite(ESub)) }
b'*' => { skip!(bs); Ok(Bite(EMul)) }
b'/' => { skip!(bs); Ok(Bite(EDiv)) }
b'%' => { skip!(bs); Ok(Bite(EMod)) }
b'^' => { skip!(bs); Ok(Bite(EExp)) }
b'<' => { skip!(bs);
if peek_is!(bs,0,b'=') { skip!(bs); Ok(Bite(ELTE)) }
else { Ok(Bite(ELT)) } }
b'>' => { skip!(bs);
if peek_is!(bs,0,b'=') { skip!(bs); Ok(Bite(EGTE)) }
else { Ok(Bite(EGT)) } }
b'=' if peek_is!(bs,1,b'=') => { skip_n!(bs,2);
Ok(Bite(EEQ)) }
b'!' if peek_is!(bs,1,b'=') => { skip_n!(bs,2);
Ok(Bite(ENE)) }
#[cfg(feature="alpha-keywords")]
b'o' if peek_is!(bs,1,b'r') => { skip_n!(bs,2);
Ok(Bite(EOR)) }
b'|' if peek_is!(bs,1,b'|') => { skip_n!(bs,2);
Ok(Bite(EOR)) }
#[cfg(feature="alpha-keywords")]
b'a' if peek_is!(bs,1,b'n') && peek_is!(bs,2,b'd') => { skip_n!(bs,3);
Ok(Bite(EAND)) }
b'&' if peek_is!(bs,1,b'&') => { skip_n!(bs,2);
Ok(Bite(EAND)) }
_ => Ok(Pass),
}
}
}
fn read_callable(&self, slab:&mut ParseSlab, bs:&mut &[u8], depth:usize) -> Result<Token<Value>,Error> {
match Self::read_varname(bs)? {
Pass => Ok(Pass),
Bite(varname) => {
match Self::read_open_parenthesis(bs)? {
Pass => {
#[cfg(feature="unsafe-vars")]
match slab.unsafe_vars.get(&varname) {
None => Ok(Bite(EStdFunc(EVar(varname)))),
Some(&ptr) => Ok(Bite(EStdFunc(EUnsafeVar{name:varname, ptr})))
}
#[cfg(not(feature="unsafe-vars"))]
Ok(Bite(EStdFunc(EVar(varname))))
}
Bite(open_parenth) => {
match varname.as_ref() {
"print" => Ok(Bite(EPrintFunc(self.read_printfunc(slab,bs,depth,open_parenth)?))),
_ => Ok(Bite(EStdFunc(self.read_func(varname,slab,bs,depth,open_parenth)?))),
}
}
}
}
}
}
fn read_varname(bs:&mut &[u8]) -> Result<Token<String>,Error> {
spaces!(bs);
let mut toklen = 0;
while Self::is_varname_byte_opt(peek_n!(bs,toklen),toklen) { toklen=toklen+1; }
if toklen==0 { return Ok(Pass); }
let out = unsafe { from_utf8_unchecked(&bs[..toklen]) }.to_string();
skip_n!(bs, toklen);
Ok(Bite(out))
}
fn read_open_parenthesis(bs:&mut &[u8]) -> Result<Token<u8>,Error> {
spaces!(bs);
match peek!(bs) {
Some(b'(') | Some(b'[') => Ok(Bite(match read!(bs) {
Ok(b) => b,
Err(..) => return Err(Error::Unreachable),
})),
_ => Ok(Pass),
}
}
fn read_func(&self, fname:String, slab:&mut ParseSlab, bs:&mut &[u8], depth:usize, open_parenth:u8) -> Result<StdFunc,Error> {
let close_parenth = match open_parenth {
b'(' => b')',
b'[' => b']',
_ => return Err(Error::Expected("'(' or '['".to_string())),
};
let mut args = Vec::<ExpressionI>::with_capacity(4);
loop {
spaces!(bs);
match peek!(bs) {
Some(b) => {
if b==close_parenth {
skip!(bs);
break;
}
}
None => return Err(Error::EofWhileParsing(fname)),
}
if !args.is_empty() {
match read!(bs) {
Ok(b',') | Ok(b';') => {
}
_ => return Err(Error::Expected("',' or ';'".to_string())),
}
}
args.push(self.read_expression(slab,bs,depth+1,false)?);
}
let fname_str = fname.as_str();
match fname_str {
"int" => {
if args.len()==1 { Ok(EFuncInt(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("int: expected one arg".to_string())) }
}
"ceil" => {
if args.len()==1 { Ok(EFuncCeil(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("ceil: expected one arg".to_string())) }
}
"floor" => {
if args.len()==1 { Ok(EFuncFloor(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("floor: expected one arg".to_string())) }
}
"abs" => {
if args.len()==1 { Ok(EFuncAbs(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("abs: expected one arg".to_string())) }
}
"sign" => {
if args.len()==1 { Ok(EFuncSign(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("sign: expected one arg".to_string())) }
}
"log" => {
if args.len()==1 { Ok(EFuncLog{base:None, expr:match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}})
} else if args.len()==2 {
let expr = match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
};
Ok(EFuncLog{base:Some(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}),
expr})
} else { Err(Error::WrongArgs("expected log(x) or log(base,x)".to_string())) }
}
"round" => {
if args.len()==1 { Ok(EFuncRound{modulus:None, expr:match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}})
} else if args.len()==2 {
let expr = match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
};
Ok(EFuncRound{modulus:Some(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}),
expr})
} else { Err(Error::WrongArgs("round: expected round(x) or round(modulus,x)".to_string())) }
}
"min" => {
if !args.is_empty() {
match remove_no_panic(&mut args, 0) {
Some(first) => Ok(EFuncMin{first, rest:args}),
None => Err(Error::Unreachable),
}
} else { Err(Error::WrongArgs("min: expected one or more args".to_string())) }
}
"max" => {
if !args.is_empty() {
match remove_no_panic(&mut args, 0) {
Some(first) => Ok(EFuncMax{first, rest:args}),
None => Err(Error::Unreachable),
}
} else { Err(Error::WrongArgs("max: expected one or more args".to_string())) }
}
"e" => {
if args.is_empty() { Ok(EFuncE)
} else { Err(Error::WrongArgs("e: expected no args".to_string())) }
}
"pi" => {
if args.is_empty() { Ok(EFuncPi)
} else { Err(Error::WrongArgs("pi: expected no args".to_string())) }
}
"sin" => {
if args.len()==1 { Ok(EFuncSin(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("sin: expected one arg".to_string())) }
}
"cos" => {
if args.len()==1 { Ok(EFuncCos(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("cos: expected one arg".to_string())) }
}
"tan" => {
if args.len()==1 { Ok(EFuncTan(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("tan: expected one arg".to_string())) }
}
"asin" => {
if args.len()==1 { Ok(EFuncASin(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("asin: expected one arg".to_string())) }
}
"acos" => {
if args.len()==1 { Ok(EFuncACos(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("acos: expected one arg".to_string())) }
}
"atan" => {
if args.len()==1 { Ok(EFuncATan(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("atan: expected one arg".to_string())) }
}
"sinh" => {
if args.len()==1 { Ok(EFuncSinH(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("sinh: expected one arg".to_string())) }
}
"cosh" => {
if args.len()==1 { Ok(EFuncCosH(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("cosh: expected one arg".to_string())) }
}
"tanh" => {
if args.len()==1 { Ok(EFuncTanH(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("tanh: expected one arg".to_string())) }
}
"asinh" => {
if args.len()==1 { Ok(EFuncASinH(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("asinh: expected one arg".to_string())) }
}
"acosh" => {
if args.len()==1 { Ok(EFuncACosH(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("acosh: expected one arg".to_string())) }
}
"atanh" => {
if args.len()==1 { Ok(EFuncATanH(match args.pop() {
Some(xi) => xi,
None => return Err(Error::Unreachable),
}))
} else { Err(Error::WrongArgs("atanh: expected one arg".to_string())) }
}
_ => {
#[cfg(feature="unsafe-vars")]
match slab.unsafe_vars.get(fname_str) {
None => Ok(EFunc{name:fname, args}),
Some(&ptr) => Ok(EUnsafeVar{name:fname, ptr}),
}
#[cfg(not(feature="unsafe-vars"))]
Ok(EFunc{name:fname, args})
}
}
}
fn read_printfunc(&self, slab:&mut ParseSlab, bs:&mut &[u8], depth:usize, open_parenth:u8) -> Result<PrintFunc,Error> {
let close_parenth = match open_parenth {
b'(' => b')',
b'[' => b']',
_ => return Err(Error::Expected("'(' or '['".to_string())),
};
let mut args = Vec::<ExpressionOrString>::with_capacity(8);
loop {
spaces!(bs);
match peek!(bs) {
Some(b) => {
if b==close_parenth {
skip!(bs);
break;
}
}
None => { return Err(Error::EofWhileParsing("print".to_string())); }
}
if !args.is_empty() {
match read!(bs) {
Ok(b',') | Ok(b';') => {}
_ => { return Err(Error::Expected("',' or ';'".to_string())); }
}
}
args.push(self.read_expressionorstring(slab,bs,depth+1)?);
}
Ok(PrintFunc(args))
}
fn read_expressionorstring(&self, slab:&mut ParseSlab, bs:&mut &[u8], depth:usize) -> Result<ExpressionOrString,Error> {
match Self::read_string(bs)? {
Pass => {}
Bite(s) => return Ok(EStr(s)),
}
Ok(EExpr(self.read_expression(slab,bs,depth+1,false)?))
}
fn read_string(bs:&mut &[u8]) -> Result<Token<String>,Error> {
spaces!(bs);
match peek!(bs) {
None => return Err(Error::EofWhileParsing("opening quote of string".to_string())),
Some(b'"') => { skip!(bs); }
Some(_) => { return Ok(Pass) }
}
let mut toklen = 0;
while match peek_n!(bs,toklen) {
None => false,
Some(b'"') => false,
Some(_) => true,
} { toklen=toklen+1; }
let out = from_utf8(&bs[..toklen]).map_err(|_| Error::Utf8ErrorWhileParsing("string".to_string()))?;
skip_n!(bs, toklen);
match read!(bs) {
Err(Error::EOF) => Err(Error::EofWhileParsing("string".to_string())),
Err(_) => Err(Error::Unreachable),
Ok(b'"') => Ok(Bite(out.to_string())),
Ok(_) => Err(Error::Unreachable),
}
}
}
impl Default for Parser {
fn default() -> Self { Self::new() }
}
impl Default for Expression {
fn default() -> Self { Expression{first:Default::default(), pairs:Vec::new()} }
}
impl Default for Value {
fn default() -> Self { EConstant(std::f64::NAN) }
}
pub(crate) fn remove_no_panic<T>(vself:&mut Vec<T>, index:usize) -> Option<T> {
let len = vself.len();
if index >= len { return None }
unsafe {
let ret;
{
let ptr = vself.as_mut_ptr().add(index);
ret = ptr::read(ptr);
ptr::copy(ptr.offset(1), ptr, len-index-1);
}
vself.set_len(len-1);
Some(ret)
}
}
#[cfg(test)]
mod internal_tests {
use super::*;
use crate::slab::Slab;
#[test]
fn rem_no_panic() {
let mut v = vec![1u8, 2, 3];
assert_eq!(format!("{:?}",v), "[1, 2, 3]");
assert_eq!(remove_no_panic(&mut v,1), Some(2));
assert_eq!(remove_no_panic(&mut v,10), None);
assert_eq!(format!("{:?}",v), "[1, 3]");
}
#[test]
fn util() {
match (|| -> Result<(),Error> {
let bsarr = [1,2,3];
let bs = &mut &bsarr[..];
assert_eq!(peek!(bs), Some(1));
assert_eq!(peek_n!(bs,1), Some(2));
assert_eq!(peek_n!(bs,2), Some(3));
assert_eq!(peek_n!(bs,3), None);
assert_eq!(read!(bs)?, 1);
skip!(bs);
assert_eq!(read!(bs)?, 3);
match read!(bs).err() {
Some(Error::EOF) => {},
_ => panic!("I expected an EOF")
}
Ok(())
})() {
Ok(_) => {}
Err(_) => {
unimplemented!();
}
}
assert!((&[0u8; 0]).is_empty());
assert!(!(&[1]).is_empty());
assert!((b"").is_empty());
assert!(!(b"x").is_empty());
let b=b' '; assert!(is_space!(b));
let b=b'\t'; assert!(is_space!(b));
let b=b'\r'; assert!(is_space!(b));
let b=b'\n'; assert!(is_space!(b));
let b=b'a'; assert!(!is_space!(b));
let b=b'1'; assert!(!is_space!(b));
let b=b'.'; assert!(!is_space!(b));
{
let bsarr = b" abc 123 ";
let bs = &mut &bsarr[..];
spaces!(bs);
assert_eq!(bs, b"abc 123 ");
}
}
#[test]
fn priv_tests() {
assert!(Parser::is_varname_byte_opt(Some(b'a'),0));
let mut slab = Slab::new();
{
let bsarr = b"12.34";
let bs = &mut &bsarr[..];
assert_eq!(Parser::new().read_value(&mut slab.ps, bs, 0), Ok(EConstant(12.34)));
}
}
}