use proc_macro::TokenStream;
use makepad_micro_proc_macro::{TokenBuilder, TokenParser, error};
use makepad_live_id::*;
fn parse_array(parser:&mut TokenParser, tb:&mut TokenBuilder)->Result<(),TokenStream>{
while !parser.eat_eot(){
let mut prop = TokenBuilder::new();
prop.add("origin:LiveNodeOrigin::empty(), id:LiveId(0)");
parse_value(prop.end(), parser, tb)?;
parser.eat_punct_alone(',');
}
Ok(())
}
fn parse_object(parser:&mut TokenParser, tb:&mut TokenBuilder)->Result<(),TokenStream>{
while !parser.eat_eot(){
let live_id = if parser.is_bracket(){ parser.open_group();
parser.eat_level()
}
else{
let mut prop = TokenBuilder::new();
let prop_id = LiveId::from_str_with_lut(&parser.expect_any_ident()?).unwrap();
prop.add("LiveId(").suf_u64(prop_id.0).add(")");
prop.end()
};
if parser.eat_punct_alone(':'){ let mut prop = TokenBuilder::new();
prop.add("origin:LiveNodeOrigin::field(), id:");
prop.stream(Some(live_id));
parse_value(prop.end(), parser, tb)?;
}
else if parser.eat_punct_alone('='){
let mut prop = TokenBuilder::new();
prop.add("origin:LiveNodeOrigin::instance(), id:");
prop.stream(Some(live_id));
parse_value(prop.end(), parser, tb)?;
} else {
return Err(parser.unexpected());
}
parser.eat_punct_alone(',');
}
Ok(())
}
fn parse_value(node_start:TokenStream, parser:&mut TokenParser, tb:&mut TokenBuilder)->Result<(),TokenStream>{
if parser.is_paren(){ parser.open_group();
let arg = parser.eat_level();
tb.add("LiveNode{").stream(Some(node_start)).add(",value:(").stream(Some(arg)).add(").to_live_value()},");
}
else if parser.is_bracket(){ tb.add("LiveNode{").stream(Some(node_start.clone())).add(",value:LiveValue::Array},");
parser.open_group();
parse_array(parser,tb)?;
tb.add("LiveNode{").stream(Some(node_start)).add(",value:LiveValue::Close},");
}
else if parser.is_brace(){ tb.add("LiveNode{").stream(Some(node_start.clone())).add(",value:LiveValue::Object},");
parser.open_group();
parse_object(parser, tb)?;
tb.add("LiveNode{").stream(Some(node_start)).add(",value:LiveValue::Close},");
}
else if let Some(class) = parser.eat_any_ident(){
let class_id = LiveId::from_str_with_lut(&class).unwrap().0;
if parser.is_brace(){
tb.add("LiveNode{").stream(Some(node_start.clone())).add(",value:LiveValue::Clone(");
tb.add("LiveId(").suf_u64(class_id).add("))},");
parser.open_group();
parse_object(parser,tb)?;
tb.add("LiveNode{").stream(Some(node_start)).add(",value:LiveValue::Close},");
}
else if class == "true"{
tb.add("LiveNode{").stream(Some(node_start)).add(",value:LiveValue::Bool(true)},");
}
else if class == "false"{
tb.add("LiveNode{").stream(Some(node_start)).add(",value:LiveValue::Bool(false)},");
}
else{
if class.chars().next().unwrap().is_uppercase(){
tb.add("LiveNode{").stream(Some(node_start)).add(",value:LiveValue::BareEnum(");
tb.add("LiveId(").suf_u64(class_id).add("))},");
}
else{
tb.add("LiveNode{").stream(Some(node_start)).add(",value:LiveValue::Id(");
tb.add("LiveId(").suf_u64(class_id).add("))},");
}
}
}
else if parser.eat_punct_alone('#'){ let color = parser.expect_any_ident()?;
let bytes = color.as_bytes();
let val = if bytes[0] == b'x'{
hex_bytes_to_u32(&bytes[1..])
}
else{
hex_bytes_to_u32(bytes)
};
if let Ok(val) = val{
tb.add("LiveNode{").stream(Some(node_start)).add(",value:LiveValue::Color(").suf_u32(val).add(")},");
}
else{
return Err(error(&format!("Can't parse color {}", color)));
}
}
else if let Some(lit) = parser.eat_literal(){
let s = lit.to_string();
let bytes = s.as_bytes();
if bytes[0] == b'"'{ let val = std::str::from_utf8(&bytes[1..bytes.len()-1]).unwrap();
tb.add("LiveNode{").stream(Some(node_start)).add(",value:LiveValue::Str(").string(val).add(")},");
}
else if s == "true" || s == "false"{
tb.add("LiveNode{").stream(Some(node_start)).add(",value:LiveValue::Bool(").ident(&s).add(")},");
}
else if s.chars().any(|c| c == '.'){
if let Ok(value) = s.parse::<f64>(){
tb.add("LiveNode{").stream(Some(node_start)).add(",value:LiveValue::Float64(").unsuf_f64(value).add(")},");
}
else{
return Err(error("Value cant be parsed"));
}
}
else if let Ok(value) = s.parse::<i64>(){
tb.add("LiveNode{").stream(Some(node_start)).add(",value:LiveValue::Int64(").unsuf_i64(value).add(")},");
}
else{
return Err(error("Value cant be parsed"));
}
}
Ok(())
}
fn parse_color(parser:&mut TokenParser, tb:&mut TokenBuilder)->Result<(),TokenStream>{
if parser.eat_punct_alone('#'){ let color = parser.eat_level().to_string();
let bytes = color.as_bytes();
let val = if bytes[0] == b'x'{
hex_bytes_to_u32(&bytes[1..])
}
else{
hex_bytes_to_u32(bytes)
};
if let Ok(val) = val{
tb.add("Vec4::from_u32(").suf_u32(val).add(")");
return Ok(())
}
}
return Err(error("Value cant be parsed"));
}
pub fn color_impl(input:TokenStream)->TokenStream{
let mut parser = TokenParser::new(input);
let mut tb = TokenBuilder::new();
if let Err(e) = parse_color(&mut parser, &mut tb){
return e
}
tb.end()
}
pub fn live_impl(input:TokenStream)->TokenStream{
let mut parser = TokenParser::new(input);
let mut tb = TokenBuilder::new();
tb.add("&[");
tb.add("LiveNode{origin:LiveNodeOrigin::empty(), id:LiveId(0),value:LiveValue::Object},");
if let Err(e) = parse_object(&mut parser, &mut tb){
return e
};
tb.add("LiveNode{origin:LiveNodeOrigin::empty(), id:LiveId(0),value:LiveValue::Close},");
tb.add("]");
tb.end()
}
pub fn live_object_impl(input:TokenStream)->TokenStream{
let mut parser = TokenParser::new(input);
let mut tb = TokenBuilder::new();
tb.add("&[");
if let Err(e) = parse_object(&mut parser, &mut tb){
return e
};
tb.add("]");
tb.end()
}
pub fn live_array_impl(input:TokenStream)->TokenStream{
let mut parser = TokenParser::new(input);
let mut tb = TokenBuilder::new();
tb.add("&[");
if let Err(e) = parse_array(&mut parser, &mut tb){
return e
};
tb.add("]");
tb.end()
}
pub fn hex_bytes_to_u32(buf: &[u8]) -> Result<u32, ()> {
fn hex_to_int(c: u8) -> Result<u32, ()> {
if (48..=57).contains(&c) {
return Ok((c - 48) as u32);
}
if (65..=70).contains(&c) {
return Ok((c - 65 + 10) as u32);
}
if (97..=102).contains(&c) {
return Ok((c - 97 + 10) as u32);
}
Err(())
}
match buf.len() {
1 => {
let val = hex_to_int(buf[0]) ?;
return Ok((val << 28) | (val << 24) | (val << 20) | (val << 16) | (val << 12) | (val << 8) | 0xff);
}
2 => { let val = (hex_to_int(buf[0]) ? << 4) + hex_to_int(buf[1]) ?;
return Ok((val << 24) | (val << 16) | (val << 8) | 0xff)
},
3 => {
let r = hex_to_int(buf[0]) ?;
let g = hex_to_int(buf[1]) ?;
let b = hex_to_int(buf[2]) ?;
return Ok((r << 28) | (r << 24) | (g << 20) | (g << 16) | (b << 12) | (b << 8) | 0xff);
}
4 => {
let r = hex_to_int(buf[0]) ?;
let g = hex_to_int(buf[1]) ?;
let b = hex_to_int(buf[2]) ?;
let a = hex_to_int(buf[3]) ?;
return Ok((r << 28) | (r << 24) | (g << 20) | (g << 16) | (b << 12) | (b << 8) | (a << 4) | a);
}
6 => {
let r = (hex_to_int(buf[0]) ? << 4) + hex_to_int(buf[1]) ?;
let g = (hex_to_int(buf[2]) ? << 4) + hex_to_int(buf[3]) ?;
let b = (hex_to_int(buf[4]) ? << 4) + hex_to_int(buf[5]) ?;
return Ok((r << 24) | (g << 16) | (b << 8) | 0xff)
}
8 => {
let r = (hex_to_int(buf[0]) ? << 4) + hex_to_int(buf[1]) ?;
let g = (hex_to_int(buf[2]) ? << 4) + hex_to_int(buf[3]) ?;
let b = (hex_to_int(buf[4]) ? << 4) + hex_to_int(buf[5]) ?;
let a = (hex_to_int(buf[6]) ? << 4) + hex_to_int(buf[7]) ?;
return Ok((r << 24) | (g << 16) | (b << 8) | a)
}
_ => (),
}
Err(())
}