Safe and convenient zero-cost goto operator implementations for RustLang.
- We do not plan to violate Rust's safety standards. We provide useful and interesting macros that partially (or fully) implement the goto operator.
Safe "goto" tree with branches of executable code.
The main branch is a branch with a single root name, it is from the main branch that code execution begins.
It is allowed to descend to the desired branch or climb the branch.
// Gtree does not use functions and is strictly on the same stack
// Technologies used are also used in gblock.
It is assumed that "gtree" will be used in parsers or other methods of logical actions.
If there is no transition to another branch in the code of the branch, it is assumed that "gtree" should complete its work.
#[macro_use]
extern crate goto;
use std::borrow::Cow;
use std::io::Read;
use std::io::Write;
use std::path::Path;
use std::io::Error;
use std::io::ErrorKind;
fn main() {
let file_path = Path::new("./gblock_logic");
let file_data: Cow<str>;
gtree! {
'checker {
// decode file
let mut file = match std::fs::File::open(&file_path) {
Ok(a) => a,
Err(e) => run_gtree!('err_load_file: e),
};
let mut buff = String::with_capacity(25);
if let Err(e) = file.read_to_string(&mut buff) {
run_gtree!('err_load_file: e);
}
if buff.is_empty() { // no empty data...
run_gtree!('err_load_file: Error::new(ErrorKind::Other, "empty file!"));
}
file_data = buff.into(); // String -> Cow<str>
};
'checker => 'err_load_file(error) {
println!("Err, read file, {:?}", error);
let mut file = match std::fs::File::create(&file_path) {
Ok(a) => a,
Err(e) => run_gtree!('full_unk_error: e),
};
let data = "FALSE";
if let Err(e) = file.write(data.as_bytes()) {
run_gtree!('full_unk_error: e);
}
file_data = data.into(); // str -> Cow<str>
};
'checker => 'full_unk_error(error) {
panic!("{:?}", error);
};
}
println!("{:?}", file_data);
}
#[macro_use]
extern crate goto;
use std::collections::HashMap;
fn main() {
let data = "BOOT_IMAGE=/boot/vmlinuz-linux-zen root=UUID=xxxx rw quiet";
let mut hash = HashMap::new();
gtree! {
#let mut buffer = Vec::with_capacity(50); // local variables
#let mut iter = data.as_bytes().iter();
#let mut a;
'decode_symbols { // root tree
//write name
loop {
a = iter.next();
match a {
Some(b'=') => {
let name = unsafe { std::string::String::from_utf8_unchecked(buffer.to_owned()) };
buffer.clear();
// write value
loop {
a = iter.next();
match a {
Some(b' ') => run_gtree!('two_value: name, {
let data = unsafe { std::string::String::from_utf8_unchecked(buffer.to_owned()) };
buffer.clear();
data
}),
Some(a) => buffer.push(*a),
None => match buffer.is_empty() { // name
true => run_gtree!('end_one_value: unsafe { std::string::String::from_utf8_unchecked(buffer) }),
false => run_gtree!('end_two_value: name, unsafe { std::string::String::from_utf8_unchecked(buffer) }),
}
}
}
},
Some(b' ') => match buffer.is_empty() {
false => run_gtree!('one_value: {
let data = unsafe { std::string::String::from_utf8_unchecked(buffer.to_owned()) };
buffer.clear();
data
}),
true => continue,
},
Some(a) => buffer.push(*a),
None => match buffer.is_empty() {
true => break 'decode_symbols, // end
false => run_gtree!('end_one_value: unsafe { std::string::String::from_utf8_unchecked(buffer) }),
}
}
}
};
// ONE_VALUE tree end_one_value
'decode_symbols => 'end_one_value(name: String) :clone_anewrun('one_value -> 'decode_symbols) {
hash.insert(name, None);
};
// TWO_VALUE tree end_one_value
'decode_symbols => 'end_two_value(name: String, value: String) :clone_anewrun('two_value -> 'decode_symbols) {
hash.insert(name, Some(value));
};
}
assert_eq!(
hash,
{
let mut check_hash = HashMap::new();
check_hash.insert("root".to_string(), Some("UUID=xxxx".to_string()));
check_hash.insert("BOOT_IMAGE".to_string(), Some("/boot/vmlinuz-linux-zen".to_string()));
check_hash.insert("rw".to_string(), None);
check_hash.insert("quiet".to_string(), None);
check_hash
},
);
}
A safe version of the "goto" prisoner in the block. Ability to move to the beginning of the block or to the end of the block.
#[macro_use]
extern crate goto;
use std::io::Write;
use std::io::Read;
use std::borrow::Cow;
use std::path::Path;
fn main() {
let file_path = Path::new("./gblock_logic");
let file_data: Cow<str>;
gblock!['is_create_file:
gblock!['decode_file:
// decode file
let mut file = match std::fs::File::open(&file_path) {
Ok(a) => a,
Err(_e) => to_end_gblock!('decode_file),
};
let mut buff = String::with_capacity(25);
if let Err(_e) = file.read_to_string(&mut buff) {
to_end_gblock!('decode_file);
}
if buff.is_empty() { // no empty data...
to_end_gblock!('decode_file);
}
file_data = buff.into(); // String -> Cow<str>
to_end_gblock!('is_create_file); //OK
];
// create new file and default value
let mut file = match std::fs::File::create(&file_path) {
Ok(a) => a,
Err(e) => panic!("{:?}", e),
};
let data = "FALSE";
if let Err(e) = file.write(data.as_bytes()) {
panic!("{:?}", e);
}
file_data = data.into(); // str -> Cow<str>
];
println!("{:?}", file_data);
}
Copyright 2020 #UlinProject (Denis Kotlyarov) Денис Котляров
Licensed under the MIT License
Licensed under the Apache License, Version 2.0