pub fn include_bytes(input: TokenStream) -> TokenStream {
    let is_log = match std::env::var("RUST_INCLUDE_BYTES_LOG") {
        Ok(res) => match res.as_str() {
            "1" | "true" => true,
            _ => false,
        },
        _ => false,
    };

    let now = std::time::Instant::now();

    let input = input.to_string();
    let input = input.trim();

    let args = match Input::parse(input) {
        Ok(args) => args,
        Err(error) => return error,
    };

    if args.file.is_empty() {
        return compile_error("Empty file name");
    }

    let mut file = match std::fs::File::open(args.file) {
        Ok(file) => file,
        Err(error) => return compile_error(format_args!("{}: Cannot open file: {}", args.file, error)),
    };

    let mut cursor = 0;
    let mut file_len = 0;
    let mut buf = [0u8; 4096];
    let mut result = "[".to_owned();

    loop {
        match std::io::Read::read(&mut file, &mut buf[cursor..]) {
            Ok(0) => {
                result.push(']');
                if cursor != 0 {
                    return compile_error(format_args!("File input with size {}b cannot be reinterpret as {}", file_len, args.typ));
                }
                break;
            },
            Ok(size) => {
                file_len += size;
                let buf_len = cursor + size;
                let written = args.typ.write_bytes(&mut result, &buf[..buf_len]);

                if written > 0 {
                    unsafe {
                        core::ptr::copy(buf.as_ptr().add(written), buf.as_mut_ptr(), buf_len - written);
                    }
                    cursor = buf_len - written;
                } else {
                    //not enough data to write expression
                    //wait another read.
                    cursor = buf_len;
                }
            },
            Err(error) => {
                return compile_error(format_args!("{}: Error reading file: {}", args.file, error))
            },
        }
    }

    if is_log {
        let elapsed = now.elapsed();
        let secs = elapsed.as_secs();
        let ms = elapsed.subsec_millis();

        if secs > 0 {
            println!("{}: parsed {}b in {}.{} seconds", args.file, file_len, secs, ms);
        } else {
            println!("{}: parsed {}b in {} ms", args.file, file_len, ms);
        }
    }

    result.parse().expect("To parse")
}
///Includes a file as a reference to a byte array.
///
///This macro will yield an expression of type [u8; N] by default with content of file.
///
///To reinterpret it as different type add `as <type>` where type can be: `u8`, `u16`, `u32`, `u64` or `u128`.
///
///# NOTE:
///
///Due to `Span::source_file` being unstable, the file is searched relative to crate root.
///
///# Supported types:
///
///- Primitive fixed sized unsigned integers;
///
///- Arrays with unsigned integers;
///
///# Usage:
///
///```
///use include_bytes_plus::include_bytes;
///
///let bytes = include_bytes!("tests/include.in");
///let bytes_u16 = include_bytes!("tests/include.in" as u16);
///let bytes_u16_2 = include_bytes!("tests/include with whitespaces.in" as u16);
///let bytes_u16_3 = include_bytes!("tests/include with whitespaces.in" as [u8; 48]);
///let bytes_u16_4 = include_bytes!("tests/include with whitespaces.in" as [u16; 12]);
///
///assert_eq!(bytes.len(), bytes_u16.len() * 2);
///assert_eq!(bytes.len(), bytes_u16_2.len() * 2);
///assert_eq!(bytes_u16_3.len(), 1);
///assert_eq!(bytes_u16_3[0].len(), 48);
///assert_eq!(bytes_u16_4.len(), 2);
///assert_eq!(bytes_u16_4[0].len(), 12);
///assert_eq!(bytes_u16_4[1].len(), 12);
///```
///
///# Debugging timings:
///
///Set env variable `RUST_INCLUDE_BYTES_LOG=1` to enable logging of each parsed file statistics
Includes a file as a reference to a byte array.
This macro will yield an expression of type [u8; N] by default with content of file.


Includes a file as a reference to a byte array . This macro will yield an expression of type [ u8 ; N ] by default with content of file .
pub fn include_bytes(input: TokenStream) -> TokenStream {
    let is_log = match std::env::var("RUST_INCLUDE_BYTES_LOG") {
        Ok(res) => match res.as_str() {
            "1" | "true" => true,
            _ => false,
        },
        _ => false,
    };
    let now = std::time::Instant::now();
    let input = input.to_string();
    let input = input.trim();
    let args = match Input::parse(input) {
        Ok(args) => args,
        Err(error) => return error,
    };
    if args.file.is_empty() {
        return compile_error("Empty file name");
    }
    let mut file = match std::fs::File::open(args.file) {
        Ok(file) => file,
        Err(error) => return compile_error(format_args!("{}: Cannot open file: {}", args.file, error)),
    };
    let mut cursor = 0;
    let mut file_len = 0;
    let mut buf = [0u8; 4096];
    let mut result = "[".to_owned();
    loop {
        match std::io::Read::read(&mut file, &mut buf[cursor..]) {
            Ok(0) => {
                result.push(']');
                if cursor != 0 {
                    return compile_error(format_args!("File input with size {}b cannot be reinterpret as {}", file_len, args.typ));
                }
                break;
            },
            Ok(size) => {
                file_len += size;
                let buf_len = cursor + size;
                let written = args.typ.write_bytes(&mut result, &buf[..buf_len]);
                if written > 0 {
                    unsafe {
                        core::ptr::copy(buf.as_ptr().add(written), buf.as_mut_ptr(), buf_len - written);
                    }
                    cursor = buf_len - written;
                } else {
                    //not enough data to write expression
                    //wait another read.
                    cursor = buf_len;
                }
            },
            Err(error) => {
                return compile_error(format_args!("{}: Error reading file: {}", args.file, error))
            },
        }
    }
    if is_log {
        let elapsed = now.elapsed();
        let secs = elapsed.as_secs();
        let ms = elapsed.subsec_millis();
        if secs > 0 {
            println!("{}: parsed {}b in {}.{} seconds", args.file, file_len, secs, ms);
        } else {
            println!("{}: parsed {}b in {} ms", args.file, file_len, ms);
        }
    }
    result.parse().expect("To parse")
}
pub fn include_bytes ( input : TokenStream ) -> TokenStream { let is_log = match std :: env :: var ( " " ) { Ok ( res ) => match res . as_str ( ) { " " | " " => true , _ => false , } , _ => false , } ; let now = std :: time :: Instant :: now ( ) ; let input = input . to_string ( ) ; let input = input . trim ( ) ; let args = match Input :: parse ( input ) { Ok ( args ) => args , Err ( error ) => return error , } ; if args . file . is_empty ( ) { return compile_error ( " " ) ; } let mut file = match std :: fs :: File :: open ( args . file ) { Ok ( file ) => file , Err ( error ) => return compile_error ( format_args ! ( " " args file error ) ) , } ; let mut cursor = 0 ; let mut file_len = 0 ; let mut buf = [ 0u8 ; 4096 ] ; let mut result = " " . to_owned ( ) ; loop { match std :: io :: Read :: read ( & mut file , & mut buf [ cursor .. ] ) { Ok ( 0 ) => { result . push ( ']' ) ; if cursor != 0 { return compile_error ( format_args ! ( " " file_len args typ ) ) ; } break ; } , Ok ( size ) => { file_len += size ; let buf_len = cursor + size ; let written = args . typ . write_bytes ( & mut result , & buf [ .. buf_len ] ) ; if written > 0 { unsafe { core :: ptr :: copy ( buf . as_ptr ( ) . add ( written ) , buf . as_mut_ptr ( ) , buf_len - written ) ; } cursor = buf_len - written ; } else { //not enough data to write expression //wait another read. cursor = buf_len ; } } , Err ( error ) => { return compile_error ( format_args ! ( " " args file error ) ) } , } } if is_log { let elapsed = now . elapsed ( ) ; let secs = elapsed . as_secs ( ) ; let ms = elapsed . subsec_millis ( ) ; if secs > 0 { println ! ( " " args file file_len secs ms ) ; } else { println ! ( " " args file file_len ms ) ; } } result . parse ( ) . expect ( " " ) }
Includes a file as a reference to a byte array.
Includes a file as a reference to a byte array .
input
TokenStream
input
TokenStream
note:
Due to `Span::source_file` being unstable, the file is searched relative to crate root.
Due to ` Span :: source_file ` being unstable the file is searched relative to crate root .
supported types:
Primitive fixed sized unsigned integers.

Arrays with unsigned integers.
Primitive fixed sized unsigned integers . Arrays with unsigned integers .
usage:
```
use include_bytes_plus::include_bytes.

let bytes = include_bytes!("tests/include.in");
let bytes_u16 = include_bytes!("tests/include.in" as u16);
let bytes_u16_2 = include_bytes!("tests/include with whitespaces.in" as u16);
let bytes_u16_3 = include_bytes!("tests/include with whitespaces.in" as [u8; 48]);
let bytes_u16_4 = include_bytes!("tests/include with whitespaces.in" as [u16; 12]).


` ` ` use include_bytes_plus :: include_bytes . let bytes = include_bytes! ( " tests / include . in " ) ; let bytes_u16 = include_bytes! ( " tests / include . in " as u16 ) ; let bytes_u16_2 = include_bytes! ( " tests / include with whitespaces . in " as u16 ) ; let bytes_u16_3 = include_bytes! ( " tests / include with whitespaces . in " as [ u8 ; 48 ] ) ; let bytes_u16_4 = include_bytes! ( " tests / include with whitespaces . in " as [ u16 ; 12 ] ) .
debugging timings:
Set env variable `RUST_INCLUDE_BYTES_LOG=1` to enable logging of each parsed file statistics
Set env variable ` RUST_INCLUDE_BYTES_LOG = 1 ` to enable logging of each parsed file statistics