Skip to content

Latest commit

 

History

History
executable file
·
227 lines (186 loc) · 6.06 KB

README.md

File metadata and controls

executable file
·
227 lines (186 loc) · 6.06 KB

Goto

Safe and convenient zero-cost goto operator implementations for RustLang.

Build Status Mit/Apache licensed crates.io Documentation

Attention!!

  1. We do not plan to violate Rust's safety standards. We provide useful and interesting macros that partially (or fully) implement the goto operator.

gtree:

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.

1 Example

#[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);
}

2 Example

#[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
		},
	);
}

gblock:

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);
}

License

Copyright 2020 #UlinProject (Denis Kotlyarov) Денис Котляров

Licensed under the MIT License

Licensed under the Apache License, Version 2.0