Skip to content

Commit

Permalink
Add first working version with log functionality
Browse files Browse the repository at this point in the history
  • Loading branch information
neersighted committed Mar 31, 2018
1 parent 62d7b28 commit f6c215f
Show file tree
Hide file tree
Showing 5 changed files with 156 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

/target
**/*.rs.bk
Cargo.lock
14 changes: 14 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
[package]
name = "rust-g"
version = "0.1.0"
authors = ["Bjorn Neergaard <bjorn@neersighted.com>"]

[lib]
crate-type = ["lib", "cdylib"]

[profile.release]
lto = true

[dependencies]
chrono = "0.4"
libc = "0.2.0"
67 changes: 67 additions & 0 deletions src/byond.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
use std::cell::Cell;
use std::ffi::{CStr, CString};
use std::slice;

use libc::{c_char, c_int};

thread_local! {
static RETURN_STRING: Cell<CString> = Cell::new(Default::default());
}

pub fn parse_args(argc: c_int, argv: *const *const c_char) -> Vec<String> {
let args: Vec<&CStr> = unsafe {
slice::from_raw_parts(argv, argc as usize)
.into_iter()
.map(|ptr| CStr::from_ptr(*ptr))
.collect()
};

args.into_iter()
.map(|cstr| cstr.to_string_lossy())
.map(|str| str.into_owned())
.collect()
}

pub fn return_string(string: Option<String>) -> *const c_char {
let cstring = match string {
Some(msg) => CString::new(msg).expect("null in returned string!"),
None => CString::new("").unwrap(),
};
let ptr = cstring.as_ptr();

RETURN_STRING.with(|cell| {
cell.set(cstring);
});

ptr as *const c_char
}

#[macro_export]
macro_rules! byond_function {
($name:ident() $body:block) => {
#[no_mangle]
pub extern "C" fn $name(
_argc: ::libc::c_int, _argv: *const *const ::libc::c_char
) -> *const ::libc::c_char {
::byond::return_string((|| $body)())
}
};

($name:ident($($arg:ident),*) $body:block) => {
#[no_mangle]
pub extern "C" fn $name(
_argc: ::libc::c_int, _argv: *const *const ::libc::c_char
) -> *const ::libc::c_char {
let __args = ::byond::parse_args(_argc, _argv);

let mut __argn = 0;
$(
let $arg = &__args[__argn];
__argn += 1;
)*

::byond::return_string((|| $body)())
}
};
}

7 changes: 7 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
extern crate chrono;
extern crate libc;

#[macro_use]
mod byond;

pub mod log;
64 changes: 64 additions & 0 deletions src/log.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use std::cell::RefCell;
use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};
use std::fs;
use std::fs::{File, OpenOptions};
use std::io;
use std::io::Write;
use std::path::Path;

use chrono::Utc;

thread_local! {
static FILE_MAP: RefCell<HashMap<String, File>> = RefCell::new(HashMap::new());
}

fn timestamp_string(data: &str) -> String {
format!("[{}] {}", Utc::now().format("%Y-%m-%d %H:%M:%S%.3f"), data)
}

fn write(filename: &str, data: String) -> Result<(), io::Error> {
FILE_MAP.with(|cell| {
let mut map = cell.borrow_mut();
let file = match map.entry(filename.to_owned()) {
Occupied(elem) => elem.into_mut(),
Vacant(elem) => {
let path = Path::new(filename);
match path.parent() {
Some(p) => fs::create_dir_all(p)?,
None => {},
};

let file = OpenOptions::new()
.append(true)
.create(true)
.open(path)?;
elem.insert(file)
},
};

writeln!(file, "{}", data)
})
}

fn close() {
FILE_MAP.with(|cell| {
let mut map = cell.borrow_mut();
map.clear();
});
}

byond_function! { log_write(filename, line) {
let line = timestamp_string(line);

match write(filename, line) {
Ok(_) => None,
Err(err) => Some(err.to_string()),
}
} }

byond_function! { log_close_all() {
close();

None
} }

0 comments on commit f6c215f

Please sign in to comment.