Skip to content

Commit

Permalink
add JSON format support
Browse files Browse the repository at this point in the history
  • Loading branch information
s1rius committed Dec 6, 2023
1 parent ad40895 commit 4873857
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 168 deletions.
11 changes: 3 additions & 8 deletions examples/hello_world/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,17 +149,12 @@ fn read_log_file_rewrite() {
writer.write_all(b"\n").unwrap();
if flag {
writer.flush().unwrap();
return None;
}
Some(0)
};

ezlog::decode::decode_with_fn(
&mut cursor,
header.version(),
&compression,
&cryptor,
&header,
my_closure,
);
ezlog::decode::decode_with_fn(&mut cursor, &compression, &cryptor, &header, my_closure);
}

const S: &str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.:;!@#$%^&*()_+-";
Expand Down
7 changes: 5 additions & 2 deletions ezlog-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ keywords = ["ezlog"]
crate-type = ["lib", "cdylib", "staticlib"]

[features]
default = []
default = ["json"]
log = ["dep:log"]
json = ["serde", "serde_json", "bitflags/serde"]
decode = ["dep:aes-gcm", "dep:regex", "dep:log"]
android_logger = ["log","dep:android_logger"]

Expand All @@ -33,9 +34,11 @@ thread-id = "4.0.0"
once_cell = "1.12"
thiserror = "1"
integer-encoding = "3.0"
bitflags = "2.0.1"
bitflags = { version = "2.0.1", features = []}
android_logger = { version = "0.13", optional = true }
regex = { version = "1", optional = true}
serde = { version = "1.0", features = ["derive"], optional = true }
serde_json = { version = "1.0", optional = true }

[target.'cfg(target_os = "android")'.dependencies]
jni = "0.21.0"
Expand Down
66 changes: 65 additions & 1 deletion ezlog-core/src/compress.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,75 @@ use std::io::{
};

use crate::{
CompressLevel,
Compression,
Decompression,
};

/// Compress type can be used to compress the log file.
#[derive(Debug, Copy, Clone, PartialEq, Hash, Eq)]
#[cfg_attr(feature = "json", derive(serde::Serialize, serde::Deserialize))]
pub enum CompressKind {
/// ZLIB compression
/// we use [flate2](https://github.com/rust-lang/flate2-rs) to implement this
ZLIB,
/// No compression
NONE,
/// Unknown compression
UNKNOWN,
}

impl From<u8> for CompressKind {
fn from(orig: u8) -> Self {
match orig {
0x00 => CompressKind::NONE,
0x01 => CompressKind::ZLIB,
_ => CompressKind::UNKNOWN,
}
}
}

impl From<CompressKind> for u8 {
fn from(orig: CompressKind) -> Self {
match orig {
CompressKind::NONE => 0x00,
CompressKind::ZLIB => 0x01,
CompressKind::UNKNOWN => 0xff,
}
}
}

/// Compress level
///
/// can be define as one of the following: FAST, DEFAULT, BEST
#[derive(Debug, Clone, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "json", derive(serde::Serialize, serde::Deserialize))]
pub enum CompressLevel {
Fast,
Default,
Best,
}

impl From<u8> for CompressLevel {
fn from(orig: u8) -> Self {
match orig {
0x00 => CompressLevel::Default,
0x01 => CompressLevel::Fast,
0x02 => CompressLevel::Best,
_ => CompressLevel::Default,
}
}
}

impl From<CompressLevel> for u8 {
fn from(orig: CompressLevel) -> Self {
match orig {
CompressLevel::Default => 0x00,
CompressLevel::Fast => 0x01,
CompressLevel::Best => 0x02,
}
}
}

pub struct ZlibCodec {
level: flate2::Compression,
}
Expand Down
3 changes: 2 additions & 1 deletion ezlog-core/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ pub struct EZLogConfig {

/// Extra info to be added to log header
///
/// Plaintext infomation write in log file header
/// Plaintext infomation write following log's header
pub extra: Option<String>,
}

Expand Down Expand Up @@ -434,6 +434,7 @@ pub(crate) fn parse_date_from_str(date_str: &str, case: &str) -> crate::Result<D
/// Log level, used to filter log records
#[repr(usize)]
#[derive(Copy, Eq, Debug)]
#[cfg_attr(feature = "json", derive(serde::Serialize, serde::Deserialize))]
pub enum Level {
/// The "error" level.
///
Expand Down
74 changes: 74 additions & 0 deletions ezlog-core/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,80 @@ use crate::{
Encryptor,
};

/// Cipher kind current support
#[derive(Debug, Copy, Clone, PartialEq, Hash, Eq)]
#[cfg_attr(feature = "json", derive(serde::Serialize, serde::Deserialize))]
pub enum CipherKind {
#[deprecated(since = "0.2.0", note = "Use AES128GCMSIV instead")]
AES128GCM,
#[deprecated(since = "0.2.0", note = "Use AES256GCMSIV instead")]
AES256GCM,
AES128GCMSIV,
AES256GCMSIV,
NONE,
UNKNOWN,
}

#[allow(deprecated)]
impl From<u8> for CipherKind {
fn from(orig: u8) -> Self {
match orig {
0x00 => CipherKind::NONE,
0x01 => CipherKind::AES128GCM,
0x02 => CipherKind::AES256GCM,
0x03 => CipherKind::AES128GCMSIV,
0x04 => CipherKind::AES256GCMSIV,
_ => CipherKind::UNKNOWN,
}
}
}

#[allow(deprecated)]
impl From<CipherKind> for u8 {
fn from(orig: CipherKind) -> Self {
match orig {
CipherKind::NONE => 0x00,
CipherKind::AES128GCM => 0x01,
CipherKind::AES256GCM => 0x02,
CipherKind::AES128GCMSIV => 0x03,
CipherKind::AES256GCMSIV => 0x04,
CipherKind::UNKNOWN => 0xff,
}
}
}

#[allow(deprecated)]
impl core::fmt::Display for CipherKind {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
match self {
CipherKind::AES128GCM => write!(f, "AEAD_AES_128_GCM"),
CipherKind::AES256GCM => write!(f, "AEAD_AES_256_GCM"),
CipherKind::AES128GCMSIV => write!(f, "AEAD_AES_128_GCM_SIV"),
CipherKind::AES256GCMSIV => write!(f, "AEAD_AES_128_GCM_SIV"),
CipherKind::NONE => write!(f, "NONE"),
_ => write!(f, "UNKNOWN"),
}
}
}

#[allow(deprecated)]
impl std::str::FromStr for CipherKind {
type Err = LogError;

fn from_str(s: &str) -> crate::Result<Self> {
match s {
"AEAD_AES_128_GCM" => Ok(CipherKind::AES128GCM),
"AEAD_AES_256_GCM" => Ok(CipherKind::AES256GCM),
"AEAD_AES_128_GCM_SIV" => Ok(CipherKind::AES128GCMSIV),
"AEAD_AES_256_GCM_SIV" => Ok(CipherKind::AES256GCMSIV),
"NONE" => Ok(CipherKind::NONE),
_ => Err(crate::errors::LogError::Parse(
"unknown cipher kind".to_string(),
)),
}
}
}

pub struct Aes256GcmSiv {
// 96-bits; unique per message
nonce: Vec<u8>,
Expand Down
49 changes: 21 additions & 28 deletions ezlog-core/src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ use crate::{
NonceGenFn,
Result,
Version,
RECORD_SIGNATURE_END,
RECORD_SIGNATURE_START,
};

Expand Down Expand Up @@ -106,18 +105,17 @@ pub fn decode_record(vec: &[u8]) -> Result<crate::EZRecord> {
#[inline]
pub(crate) fn decode_record_from_read(
reader: &mut Cursor<Vec<u8>>,
version: &Version,
compression: &Option<Box<dyn Compress>>,
cryptor: &Option<Box<dyn Cryptor>>,
header: &Header,
position: u64,
) -> Result<Vec<u8>> {
let chunk = decode_record_to_content(reader, version)?;
let chunk = decode_record_to_content(reader, &header.version)?;
let combine = crate::logger::combine_time_position(header.timestamp.unix_timestamp(), position);

let op = Box::new(move |input: &[u8]| crate::logger::xor_slice(input, &combine));
if header.has_record() && !header.is_extra_index(position) {
decode_record_content(version, &chunk, compression, cryptor, op)
decode_record_content(&header.version, &chunk, compression, cryptor, op)
} else {
Ok(chunk)
}
Expand All @@ -138,10 +136,8 @@ pub(crate) fn decode_record_to_content(
let content_size: usize = decode_record_size(reader, version)?;
let mut chunk = vec![0u8; content_size];
reader.read_exact(&mut chunk)?;
let end_sign = reader.read_u8()?;
if RECORD_SIGNATURE_END != end_sign {
//return Err(LogError::Parse("record end sign error".to_string()));
}
// ignore the end sign check
let _ = reader.read_u8()?;
Ok(chunk)
}

Expand Down Expand Up @@ -198,24 +194,24 @@ pub fn decode_record_content(

pub fn decode_with_fn<F>(
reader: &mut Cursor<Vec<u8>>,
version: &Version,
compression: &Option<Box<dyn Compress>>,
cryptor: &Option<Box<dyn Cryptor>>,
header: &Header,
mut op: F,
) where
F: for<'a> FnMut(&'a Vec<u8>, bool),
F: for<'a> FnMut(&'a Vec<u8>, bool) -> Option<u64>,
{
loop {
let position: u64 = reader.position();
match decode_record_from_read(reader, version, compression, cryptor, header, position) {
Ok(buf) => {
if buf.is_empty() {
op(&buf, true);
break;
match decode_record_from_read(reader, compression, cryptor, header, position) {
Ok(buf) => match op(&buf, buf.is_empty()) {
Some(skip) => {
if skip > 0 {
reader.set_position(reader.position() + skip);
}
}
op(&buf, false);
}
None => break,
},
Err(e) => match e {
LogError::IoError(err) => {
if err.kind() == io::ErrorKind::UnexpectedEof {
Expand Down Expand Up @@ -255,18 +251,13 @@ pub fn decode_with_writer(
.flush()
.unwrap_or_else(|e| error!(target: "ezlog_decode", "{}", e));
tx.send(())
.unwrap_or_else(|e| error!(target: "ezlog_decode", "{}", e))
.unwrap_or_else(|e| error!(target: "ezlog_decode", "{}", e));
return None;
}
Some(0)
};

decode_with_fn(
cursor,
header.version(),
&compression,
&decryptor,
header,
write_closure,
);
decode_with_fn(cursor, &compression, &decryptor, header, write_closure);
rx.recv_timeout(Duration::from_secs(60 * 5))
.map_err(|e| LogError::Parse(format!("{}", e)))
}
Expand Down Expand Up @@ -358,11 +349,12 @@ mod tests {
}
if is_end {
tx.send(()).expect("Could not send signal on channel.");
return None;
}
Some(0)
};
crate::decode::decode_with_fn(
reader,
&logger.config.version,
&logger.compression,
&logger.cryptor,
header,
Expand Down Expand Up @@ -436,11 +428,12 @@ mod tests {
}
if is_end {
tx.send(()).expect("Could not send signal on channel.");
return None;
}
Some(0)
};
crate::decode::decode_with_fn(
reader,
&logger.config.version,
&logger.compression,
&logger.cryptor,
header,
Expand Down
Loading

0 comments on commit 4873857

Please sign in to comment.