Skip to content

Commit

Permalink
Merge pull request #7 from Szune/dev
Browse files Browse the repository at this point in the history
Add serializing/deserializing ipv4
  • Loading branch information
Szune authored Nov 12, 2020
2 parents 6742cf3 + b591ccd commit fbd6fe1
Show file tree
Hide file tree
Showing 13 changed files with 181 additions and 13 deletions.
2 changes: 1 addition & 1 deletion aeon/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion aeon/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "aeon"
version = "0.2.0"
version = "0.3.0"
authors = ["Szune <[email protected]>"]
edition = "2018"
description = "A configuration file format with macros for brevity."
Expand Down
21 changes: 21 additions & 0 deletions aeon/src/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ pub trait AeonConvert {
fn str(self) -> Option<String>;
fn int(self) -> Option<i64>;
fn double(self) -> Option<f64>;
fn ip(self) -> Option<std::net::IpAddr>;
fn ip_str(self) -> Option<String>;
fn map(self) -> Option<HashMap<String,AeonValue>>;
fn list(self) -> Option<Vec<AeonValue>>;
fn get(&self, prop: &str) -> Option<AeonValue>;
Expand Down Expand Up @@ -48,6 +50,17 @@ impl AeonConvert for AeonValue {
try_convert!(self, AeonValue::Double)
}

fn ip(self) -> Option<std::net::IpAddr> {
try_convert!(self, AeonValue::Ip)
}

fn ip_str(self) -> Option<String> {
match self {
AeonValue::Ip(ip) =>Some(ip.to_string()),
_ => None,
}
}

fn map(self) -> Option<HashMap<String,AeonValue>> {
try_convert!(self, AeonValue::Map)
}
Expand Down Expand Up @@ -123,6 +136,14 @@ impl AeonConvert for Option<AeonValue> {
opt_convert!(self, double)
}

fn ip(self) -> Option<std::net::IpAddr> {
opt_convert!(self, ip)
}

fn ip_str(self) -> Option<String> {
opt_convert!(self, ip_str)
}

fn map(self) -> Option<HashMap<String,AeonValue>> {
opt_convert!(self, map)
}
Expand Down
14 changes: 14 additions & 0 deletions aeon/src/convert_panic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ pub trait AeonConvert {
fn str(self) -> String;
fn int(self) -> i64;
fn double(self) -> f64;
fn ip(self) -> std::net::IpAddr;
fn ip_str(self) -> String;
fn map(self) -> HashMap<String,AeonValue>;
fn list(self) -> Vec<AeonValue>;
fn get(&self, prop: &str) -> AeonValue;
Expand Down Expand Up @@ -48,6 +50,18 @@ impl AeonConvert for AeonValue {
panic_convert!(self, AeonValue::Double)
}

fn ip(self) -> std::net::IpAddr {
panic_convert!(self, AeonValue::Ip)
}

fn ip_str(self) -> String {
match self {
AeonValue::Ip(ip) => ip.to_string(),
_ => panic!("Invalid value conversion for {:?}", self),
}
}


fn map(self) -> HashMap<String,AeonValue> {
panic_convert!(self, AeonValue::Map)
}
Expand Down
1 change: 1 addition & 0 deletions aeon/src/deserializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,7 @@ impl <'a> Deserializer<'a> {

fn deserialize_constants(&mut self, tok: &Token) -> Result<AeonValue, String> {
match tok {
Token::Ip(ip) => Ok(AeonValue::Ip(*ip)),
Token::String(s) => Ok(AeonValue::String(s.clone())),
Token::Integer(i) => Ok(AeonValue::Integer(*i)),
Token::Double(d) => Ok(AeonValue::Double(*d)),
Expand Down
20 changes: 20 additions & 0 deletions aeon/src/flags.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
use std::ops::{BitAnd, BitOrAssign};

#[inline]
pub fn has<T>(value: T, flag: T) -> bool
where
T: BitAnd<Output = T> +
Copy +
PartialEq +
Eq,
{
value & flag == flag
}

#[inline]
pub fn add<T>(value: &mut T, flag: T) -> ()
where
T: BitOrAssign + Copy
{
*value |= flag;
}
77 changes: 68 additions & 9 deletions aeon/src/lexer.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
use std::str::Chars;
use std::str::{Chars, FromStr};
use crate::token::Token;
use crate::flags;

pub struct Lexer<'a> {
code: Chars<'a>,
prev: Option<char>,
}


impl <'a> Lexer<'a> {
pub fn new(code: &'a String) -> Lexer<'a> {
Lexer {
Expand Down Expand Up @@ -68,7 +71,8 @@ impl <'a> Lexer<'a> {
'@' => Ok(Some(Token::At)),
'a' ..= 'z' | 'A' ..= 'Z' => self.get_identifier(now),
'"' => self.get_string(),
'0'..='9' | '-' => self.get_number(now),
'0'..='9' => self.get_number_or_ip(now),
'-' => self.get_number(now),
_ => Err(format!("Unknown char {}",now)),
}
}
Expand Down Expand Up @@ -102,23 +106,77 @@ impl <'a> Lexer<'a> {
}
}

const FLAG_HAS_DECIMAL_POINT : u8 = 1;
const FLAG_HAS_DECIMALS : u8 = 2;
const FLAG_IS_IP : u8 = 4;

fn get_number_or_ip(&mut self, c: char) -> Result<Option<Token>, String> {
let mut t_str = String::with_capacity(10);
let mut num_flags = 0u8;
t_str.push(c);
while let Some(t) = self.code.next() {
match t {
'0' ..= '9' | '_' => {
if flags::has(num_flags, Self::FLAG_HAS_DECIMAL_POINT) {
flags::add(&mut num_flags, Self::FLAG_HAS_DECIMALS);
}
t_str.push(t);
},
'.' => {
if flags::has(num_flags, Self::FLAG_HAS_DECIMAL_POINT) &&
!flags::has(num_flags, Self::FLAG_HAS_DECIMALS) {
return Err(format!("Two decimal points in number: {}", t_str))
} else if flags::has(num_flags, Self::FLAG_HAS_DECIMALS) {
flags::add(&mut num_flags, Self::FLAG_IS_IP);
} else if !flags::has(num_flags, Self::FLAG_HAS_DECIMAL_POINT) {
flags::add(&mut num_flags, Self::FLAG_HAS_DECIMAL_POINT);
}
t_str.push(t);
},
p => {
self.prev = Some(p);
break;
},
}
}

t_str.shrink_to_fit();
if flags::has(num_flags, Self::FLAG_IS_IP) {
Ok(Some(Token::Ip(
std::net::IpAddr::V4(
std::net::Ipv4Addr::from_str(t_str.as_str())
.map_err(|e| e.to_string())?
)
)))
} else if flags::has(num_flags, Self::FLAG_HAS_DECIMAL_POINT) {
if flags::has(num_flags, Self::FLAG_HAS_DECIMALS) {
Ok(Some(Token::Double(t_str.parse().unwrap())))
}
else{
Err("bad".into())
}
} else {
Ok(Some(Token::Integer(t_str.parse().unwrap())))
}
}

fn get_number(&mut self, c: char) -> Result<Option<Token>, String> {
let mut t_str = String::with_capacity(10);
let mut flags = 0;
let mut num_flags = 0u8;
t_str.push(c);
while let Some(t) = self.code.next() {
match t {
'0' ..= '9' | '_' => {
if flags & 1 == 1 {
flags |= 2;
if flags::has(num_flags, Self::FLAG_HAS_DECIMAL_POINT) {
flags::add(&mut num_flags, Self::FLAG_HAS_DECIMALS);
}
t_str.push(t);
},
'.' => {
if flags & 1 == 1 {
if flags::has(num_flags, Self::FLAG_HAS_DECIMAL_POINT) {
return Err(format!("Two decimal points in number: {}", t_str))
}
flags |= 1;
flags::add(&mut num_flags, Self::FLAG_HAS_DECIMAL_POINT);
t_str.push(t);
},
p => {
Expand All @@ -129,8 +187,9 @@ impl <'a> Lexer<'a> {
}

t_str.shrink_to_fit();
if flags & 1 == 1 {
if flags & 2 == 2 {
if flags::has(num_flags, Self::FLAG_HAS_DECIMAL_POINT) {
if flags::has(num_flags, Self::FLAG_HAS_DECIMALS) {
println!("has all the flags!");
Ok(Some(Token::Double(t_str.parse().unwrap())))
}
else{
Expand Down
1 change: 1 addition & 0 deletions aeon/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod deserializer;
mod token;
pub mod convert;
pub mod convert_panic;
mod flags;

pub fn serialize(aeon: object::AeonObject) -> String {
if aeon.is_empty { return String::new() }
Expand Down
14 changes: 14 additions & 0 deletions aeon/src/serializer.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::object::{AeonObject, Macro, AeonProperty};
use crate::value::{AeonValue};
use std::net::IpAddr;

macro_rules! serialize_arg(
($s:ident, $idx:ident, $val:expr) => {
Expand Down Expand Up @@ -190,6 +191,19 @@ impl AeonFormatter for PrettySerializer {
s.push('}');
}
}
AeonValue::Ip(ip) => {
match ip {
IpAddr::V4(v4) => {
let octets = v4.octets()
.iter()
.map(|o|o.to_string())
.collect::<Vec<String>>()
.join(".");
s.push_str(octets.as_str());
}
IpAddr::V6(_) => {todo!()}
}
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions aeon/src/token.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub enum Token {
String(String),
Integer(i64),
Double(f64),
Ip(std::net::IpAddr),
At,
True,
False,
Expand Down
1 change: 1 addition & 0 deletions aeon/src/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ pub enum AeonValue {
Double(f64),
Map(HashMap<String,AeonValue>),
List(Vec<AeonValue>),
Ip(std::net::IpAddr),
}
29 changes: 27 additions & 2 deletions aeon/tests/deserializer.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,39 @@
#[cfg(test)]
mod tests {
use aeon::convert::{AeonObjectConvert, AeonConvert};
use aeon::value::AeonValue;

#[test]
pub fn deserialize_map_with_both_quoted_and_not_quoted_keys() {
let mut aeon = r#"map: {test: 1, "two": 2}"#.into();
let aeon = r#"map: {test: 1, "two": 2}"#.into();
let ser = aeon::deserialize(aeon).expect("failed to deserialize");

assert_eq!(ser.get_path("map/test").int(), Some(1));
assert_eq!(ser.get_path("map/two").int(), Some(2));
}

#[test]
pub fn deserialize_double() {
let aeon = r#"doub: 2.10"#.into();
let ser = aeon::deserialize(aeon).expect("failed to deserialize");

assert_eq!(ser.get("doub").double(), Some(2.10));
}

#[test]
pub fn deserialize_ip() {
let aeon = r#"ip: 127.2.3.4"#.into();
let ser = aeon::deserialize(aeon).expect("failed to deserialize");

assert_eq!(ser.get("ip").ip(),
Some(std::net::IpAddr::V4(std::net::Ipv4Addr::new(127,2,3,4))));
}

#[test]
pub fn deserialize_ip_and_get_as_string() {
let aeon = r#"ip: 127.2.3.4"#.into();
let ser = aeon::deserialize(aeon).expect("failed to deserialize");

assert_eq!(ser.get("ip").ip_str(),
Some(String::from("127.2.3.4")));
}
}
11 changes: 11 additions & 0 deletions aeon/tests/serializer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,17 @@ mod tests {
assert_eq!("character: \"erki isthename\"\n\n", ser);
}

#[test]
pub fn serialize_ip_property() {
let mut aeon = AeonObject::new();
let aeon_value = AeonProperty::new(
"ip".into(),
AeonValue::Ip(std::net::IpAddr::V4(std::net::Ipv4Addr::new(127, 1, 2, 3))));
aeon.add_property(aeon_value);
let ser = aeon::serialize(aeon);
assert_eq!("ip: 127.1.2.3\n\n", ser);
}

#[test]
pub fn serialize_list_of_ints() {
let mut aeon = AeonObject::new();
Expand Down

0 comments on commit fbd6fe1

Please sign in to comment.