Skip to content

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

License

Apache-2.0 and 2 other licenses found

Licenses found

Apache-2.0
LICENSE
Apache-2.0
LICENSE_APACHE
MIT
LICENSE_MIT
Notifications You must be signed in to change notification settings

clucompany/Goto

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

22 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

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

Releases

No releases published

Packages

No packages published

Languages