From c0a95222039656d4446c58bd381f188cd4de7dc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=94=D0=B5=D0=BD=D0=B8=D1=81=20=D0=9A=D0=BE=D1=82=D0=BB?= =?UTF-8?q?=D1=8F=D1=80=D0=BE=D0=B2?= Date: Sat, 10 Nov 2018 16:43:12 +0300 Subject: [PATCH] 1. Fix translate 2. General transformation 3. Fix Cargo.toml --- Cargo.toml | 10 +-- README.md | 8 +- examples/use.rs | 15 ++++ src/lib.rs | 209 ++++----------------------------------------- src/nightly/mod.rs | 187 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 230 insertions(+), 199 deletions(-) create mode 100644 examples/use.rs create mode 100644 src/nightly/mod.rs diff --git a/Cargo.toml b/Cargo.toml index 61517d7..5263947 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,19 +1,19 @@ [package] name = "clucstr" -version = "0.1.4" +version = "0.1.6" authors = ["Денис Котляров <#Ulin Project 18, denis2005991@gmail.com>"] repository = "https://github.com/clucompany/cluCStr.git" + license = "Apache-2.0" readme = "README.md" -description = "Creation of CStr with zero cost. Plugin for rust compiler." -keywords = ["cstr", "clucstr", "clucompany"] +description = "Creation of strings C with zero cost. A plug-in for the rust compiler." +keywords = ["cstr", "clucstr", "create_cstr", "clucompany"] categories = ["development-tools::ffi"] +[features] [lib] -name = "clucstr" -crate-type = ["dylib", "rlib"] plugin = true [dependencies] diff --git a/README.md b/README.md index 07f600c..d2a5d9c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,13 @@ [![crates.io](http://meritbadge.herokuapp.com/clucstr)](https://crates.io/crates/clucstr) [![Documentation](https://docs.rs/clucstr/badge.svg)](https://docs.rs/clucstr) -Secure creation of CStr with zero cost. Plugin for rust compiler. +Creation of strings C with zero cost. A plug-in for the rust compiler. + +# Features +1. The transparent creation of the C strings with zero cost. +2. Check of the C lines at the level of the compiler. +3. Convenient macro for creation of lines. +4. Plug-in for the compiler. # Use diff --git a/examples/use.rs b/examples/use.rs new file mode 100644 index 0000000..f3a5b3f --- /dev/null +++ b/examples/use.rs @@ -0,0 +1,15 @@ + +#![feature(plugin)] +#![plugin(clucstr)] + +use std::ffi::CStr; + +fn main() { + let c_str = cstr!(12u8); + + my_function(c_str); +} + +fn my_function>(a: A) { + println!("{:?}", a.as_ref()); +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 2c8bbb3..e9ef798 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -17,7 +17,15 @@ // /*! -Secure creation of CStr with zero cost. Plugin for rust compiler. +Creation of strings C with zero cost. A plug-in for the rust compiler. + +# Features +1. The transparent creation of the C strings with zero cost. +2. Check of the C lines at the level of the compiler. +3. Convenient macro for creation of lines. +4. Plug-in for the compiler. + + # Use ``` @@ -142,201 +150,16 @@ test tests::cstr_macros ... bench: 90 ns/iter (+/- 14) test tests::cstr_plugin ... bench: 0 ns/iter (+/- 0) */ -#![feature(plugin_registrar, rustc_private)] -#![feature(i128_type)] -extern crate syntax; -extern crate rustc; -extern crate rustc_plugin; -use syntax::tokenstream::TokenTree; -use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; -use syntax::ext::build::AstBuilder; -use syntax::ext::quote::rt::Span; -use rustc_plugin::Registry; -use syntax::ast::ExprKind; -use syntax::ast::LitKind; -use syntax::ast::Mutability; -use syntax::ast::LitIntType; -use syntax::ast::TyKind; -use syntax::ast::UintTy; -use syntax::ast::UnOp; -use syntax::ast::BlockCheckMode; -use syntax::ast::UnsafeSource; -use syntax::ast::Block; -use syntax::ptr::P; -use syntax::ast; - -///Secure creation of CStr with zero cost -//Required for docks!!!!! -#[macro_export] -macro_rules! cstr { - ($s:expr) => {}; -} -//Required for docks!!!!! - - -#[doc(hidden)] -#[plugin_registrar] -pub fn plugin_registrar(reg: &mut Registry) { - reg.register_macro("cstr", cstr); -} - -#[doc(hidden)] -pub fn cstr(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> Box { - let mut parser = cx.new_parser_from_tts(args); - - let expr = match parser.parse_expr() { - Ok(a) => a, - Err(_e) => { - cx.span_err(sp, "cstr currently only supports one argument"); - return DummyResult::any(sp); - } - }; - - let c_array = { - let mut add_null = true; - - let mut array = match expr.node { - ExprKind::Lit(ref l) => { - //println!("{:?}", l.node); - match l.node { - LitKind::Str(s, _) => { - let s = s.to_string(); - let array = s.as_bytes(); - let array_len = array.len(); - - let mut vec_result = Vec::with_capacity(array_len); - - for (num, a) in array.iter().enumerate() { - if *a == 0 { - match num+1 == array_len { - true => add_null = false, - _ => { - cx.span_err(sp, "the string has a null byte"); - return DummyResult::any(sp); - }, - } - } - vec_result.push( - cx.expr_lit(sp, - LitKind::Int(*a as u128, LitIntType::Unsigned(UintTy::U8)), - ) - ); - } - vec_result - }, - LitKind::ByteStr(ref array) => { - let array_len = array.len(); - let mut vec_result = Vec::with_capacity(array.len()); - - for (num, a) in array.iter().enumerate() { - if *a == 0 { - match num+1 == array_len { - true => add_null = false, - _ => { - cx.span_err(sp, "the string has a null byte"); - return DummyResult::any(sp); - }, - } - } - vec_result.push( - cx.expr_lit(sp, - LitKind::Int(*a as u128, LitIntType::Unsigned(UintTy::U8)), - ) - ); - } - vec_result - }, - LitKind::Byte(ref a) => { - if *a == 0 { - add_null = false; - } - vec!( - cx.expr_lit(sp, - LitKind::Int(*a as u128, LitIntType::Unsigned(UintTy::U8)), - ) - ) - } - _ => { - cx.span_err(sp, "argument should be a single identifier"); - return DummyResult::any(sp); - } - - } - }, - _ => { - cx.span_err(sp, "argument should be a single identifier"); - return DummyResult::any(sp); - } - }; - - if add_null { - array.reserve(1); - array.push( - cx.expr_lit(sp, - LitKind::Int(0, LitIntType::Unsigned(UintTy::U8)), - ) - ); - } - - cx.expr( - sp, - ExprKind::AddrOf(Mutability::Immutable, - cx.expr(sp, ExprKind::Array(array)) //[u8] - ) // &[u8] - ) - }; - - let c_array = cx.expr_cast( - sp, - c_array, //[u8] - cx.ty_ptr(sp, // -> *const [u8] - cx.ty(sp, TyKind::Slice( - cx.ty_ident(sp, cx.ident_of("u8")) - )), // P - - Mutability::Immutable // const - ) - );// &[u8] as *const [u8] - - let c_cstr = cx.expr_cast( - sp, - c_array, //[i8] - cx.ty_ptr(sp, // -> *const [i8] - cx.ty_ident(sp, cx.ident_of("CStr")), - - Mutability::Immutable // const - ) - ); // as *const CSTR - - let c_cstr = cx.expr_unary(sp, UnOp::Deref, c_cstr); - //*([u8] as *const [u8] as *const CStr) - - let c_cstr = cx.expr(sp, ExprKind::AddrOf(Mutability::Immutable, c_cstr)); - //&*([u8] as *const [u8] as *const CStr) - - let block = { - let vec_stmts = vec!( - cx.stmt_expr(c_cstr) - ); - let mut block = P(Block { - stmts: vec_stmts, - id: ast::DUMMY_NODE_ID, - rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated), - span: sp, - recovered: false, - - }); - cx.expr_block(block) - };// unsafe { &*([u8] as *const [u8] as *const CStr) } - - - MacEager::expr( - block - ) -} +#![feature(plugin_registrar)] +#![feature(rustc_private)] +extern crate syntax; +extern crate rustc; +extern crate rustc_plugin; +mod nightly; +pub use self::nightly::*; diff --git a/src/nightly/mod.rs b/src/nightly/mod.rs new file mode 100644 index 0000000..56c8845 --- /dev/null +++ b/src/nightly/mod.rs @@ -0,0 +1,187 @@ + +use syntax::tokenstream::TokenTree; +use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacEager}; +use syntax::ext::build::AstBuilder; +use syntax::ext::quote::rt::Span; +use rustc_plugin::Registry; +use syntax::ast::ExprKind; +use syntax::ast::LitKind; +use syntax::ast::Mutability; +use syntax::ast::LitIntType; +use syntax::ast::TyKind; +use syntax::ast::UintTy; +use syntax::ast::UnOp; +use syntax::ast::BlockCheckMode; +use syntax::ast::UnsafeSource; +use syntax::ast::Block; +use syntax::ptr::P; +use syntax::ast; + +///Safe creation of CStr with zero cost +//It is required for documentation! +#[macro_export] +macro_rules! cstr { + ($s:expr) => {}; +} +//It is required for documentation! + + +#[doc(hidden)] +#[plugin_registrar] +pub fn plugin_registrar(reg: &mut Registry) { + reg.register_macro("cstr", cstr); +} + +#[doc(hidden)] +pub fn cstr(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree]) -> Box { + let mut parser = cx.new_parser_from_tts(args); + + let expr = match parser.parse_expr() { + Ok(a) => a, + Err(_e) => { + cx.span_err(sp, "cstr only supports now one parameter"); + return DummyResult::any(sp); + } + }; + + let c_array = { + let mut add_null = true; + + let mut array = match expr.node { + ExprKind::Lit(ref l) => { + match l.node { + LitKind::Str(s, _) => { + let s = s.to_string(); + let array = s.as_bytes(); + let array_len = array.len(); + + let mut vec_result = Vec::with_capacity(array_len); + + for (num, a) in array.iter().enumerate() { + if *a == 0 { + match num+1 == array_len { + true => add_null = false, + _ => { + cx.span_err(sp, "in line not admissible characters are found."); + return DummyResult::any(sp); + }, + } + } + vec_result.push( + cx.expr_lit(sp, + LitKind::Int(*a as u128, LitIntType::Unsigned(UintTy::U8)), + ) + ); + } + vec_result + }, + LitKind::ByteStr(ref array) => { + let array_len = array.len(); + let mut vec_result = Vec::with_capacity(array.len()); + + for (num, a) in array.iter().enumerate() { + if *a == 0 { + match num+1 == array_len { + true => add_null = false, + _ => { + cx.span_err(sp, "in line not admissible characters are found."); + return DummyResult::any(sp); + }, + } + } + vec_result.push( + cx.expr_lit(sp, + LitKind::Int(*a as u128, LitIntType::Unsigned(UintTy::U8)), + ) + ); + } + vec_result + }, + LitKind::Byte(ref a) => { + if *a == 0 { + add_null = false; + } + vec!( + cx.expr_lit(sp, + LitKind::Int(*a as u128, LitIntType::Unsigned(UintTy::U8)), + ) + ) + } + _ => { + cx.span_err(sp, "not incorrect data are transferred to a macro"); + return DummyResult::any(sp); + } + + } + }, + _ => { + cx.span_err(sp, "not incorrect data are transferred to a macro"); + return DummyResult::any(sp); + } + }; + + if add_null { + array.reserve(1); + array.push( + cx.expr_lit(sp, + LitKind::Int(0, LitIntType::Unsigned(UintTy::U8)), + ) + ); + } + + cx.expr( + sp, + ExprKind::AddrOf(Mutability::Immutable, + cx.expr(sp, ExprKind::Array(array)) //[u8] + ) // &[u8] + ) + }; + + let c_array = cx.expr_cast( + sp, + c_array, //[u8] + cx.ty_ptr(sp, // -> *const [u8] + cx.ty(sp, TyKind::Slice( + cx.ty_ident(sp, cx.ident_of("u8")) + )), // P + + Mutability::Immutable // const + ) + );// &[u8] as *const [u8] + + let c_cstr = cx.expr_cast( + sp, + c_array, //[i8] + cx.ty_ptr(sp, // -> *const [i8] + cx.ty_ident(sp, cx.ident_of("CStr")), + + Mutability::Immutable // const + ) + ); // as *const CSTR + + let c_cstr = cx.expr_unary(sp, UnOp::Deref, c_cstr); + //*([u8] as *const [u8] as *const CStr) + + let c_cstr = cx.expr(sp, ExprKind::AddrOf(Mutability::Immutable, c_cstr)); + //&*([u8] as *const [u8] as *const CStr) + + let block = { + let vec_stmts = vec!( + cx.stmt_expr(c_cstr) + ); + let mut block = P(Block { + stmts: vec_stmts, + id: ast::DUMMY_NODE_ID, + rules: BlockCheckMode::Unsafe(UnsafeSource::CompilerGenerated), + span: sp, + recovered: false, + + }); + cx.expr_block(block) + };// unsafe { &*([u8] as *const [u8] as *const CStr) } + + + MacEager::expr( + block + ) +}