Skip to content

Commit

Permalink
add nested struct parsing
Browse files Browse the repository at this point in the history
  • Loading branch information
Shourya742 committed Dec 30, 2024
1 parent 3f957e6 commit 742bcde
Show file tree
Hide file tree
Showing 10 changed files with 265 additions and 92 deletions.
3 changes: 0 additions & 3 deletions utils/sv2_serde_json/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,3 @@ edition = "2021"

[dependencies]
sv2_serde_json_macros = {path = "../sv2_serde_json_macros"}
[[example]]
path = "examples/json.rs"
name = "json"
23 changes: 20 additions & 3 deletions utils/sv2_serde_json/examples/derive_macro_example.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
use sv2_serde_json_macros::{SerJson, DeJson};
use sv2_serde_json::value::{Value, Number};
use sv2_serde_json::value::{Number, Value};
use sv2_serde_json_macros::{DeJson, SerJson};

#[derive(SerJson, DeJson, Debug)]
#[derive(SerJson, DeJson, Debug, Clone)]
struct Person {
name: String,
age: i64,
is_student: bool,
here: Vec<String>,
}

#[derive(SerJson, DeJson, Debug)]
struct Person2 {
person: Person,
}

#[derive(SerJson, DeJson, Debug)]
Expand All @@ -20,6 +26,11 @@ fn main() {
name: "Alice".to_string(),
age: 25,
is_student: true,
here: vec!["HEre".to_string()],
};

let person2 = Person2 {
person: person.clone(),
};

let person_json = person.to_json_value();
Expand All @@ -28,6 +39,12 @@ fn main() {
let deserialized_person = Person::from_json_value(person_json).unwrap();
println!("Deserialized: {:?}", deserialized_person);

let person2_json = person2.to_json_value();
println!("Serialized: {:?}", person2_json.to_json_string());

let deserialized_person2 = Person2::from_json_value(person2_json).unwrap();
println!("Deserialized: {:?}", deserialized_person2);

let status = Status::Active;
let status_json = status.to_json_value();
println!("Serialized Enum: {:?}", status_json);
Expand Down
2 changes: 1 addition & 1 deletion utils/sv2_serde_json/examples/reader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ fn main() {
let parser = JsonParser::parse(file).unwrap();

dbg!(parser);
}
}
8 changes: 3 additions & 5 deletions utils/sv2_serde_json/examples/reader_writer.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use std::fs::File;
use std::io::Write;
use std::{fs::File, io::Write};

use sv2_serde_json::parser::JsonParser;
use sv2_serde_json::value::Value;
use sv2_serde_json::{parser::JsonParser, value::Value};

fn write_value_to_file(value: &Value, file_path: &str) -> std::io::Result<()> {
let json_bytes = value.to_json_bytes();
Expand All @@ -18,4 +16,4 @@ fn main() {
let _ = write_value_to_file(&parser, "./examples/result.json");

dbg!(parser);
}
}
5 changes: 2 additions & 3 deletions utils/sv2_serde_json/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

pub mod parser;
pub mod reader;
pub mod value;
pub mod token;
pub mod parser;
pub mod value;
40 changes: 25 additions & 15 deletions utils/sv2_serde_json/src/parser.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
use std::{collections::HashMap, fs::File, io::{BufReader, Cursor}, iter::Peekable, slice::Iter};
use std::{
collections::HashMap,
fs::File,
io::{BufReader, Cursor},
iter::Peekable,
slice::Iter,
};

use crate::{token::{Jsontokensizer, Token}, value::Value};
use crate::{
token::{Jsontokensizer, Token},
value::Value,
};

/// Main parser which is the entrypoint for parsing JSON
pub struct JsonParser;

impl JsonParser {


pub fn parse_from_bytes<'a>(input: &'a[u8]) -> Result<Value, ()> {
pub fn parse_from_bytes<'a>(input: &'a [u8]) -> Result<Value, ()> {
let mut json_tokenizer = Jsontokensizer::<BufReader<Cursor<&[u8]>>>::from_bytes(input);
let tokens = json_tokenizer.tokensize_json()?;
Ok(Self::tokens_to_value(tokens))
Expand All @@ -34,32 +41,37 @@ impl JsonParser {
Token::Number(number) => {
value = Value::Number(*number);
}
Token::ArrayOpen => {
value = Value::Array(Self::process_array(&mut iterator))
}
Token::ArrayOpen => value = Value::Array(Self::process_array(&mut iterator)),
Token::Boolean(boolean) => value = Value::Boolean(*boolean),
Token::Null => value = Value::Null,
Token::Comma | Token::CurlyClose | Token::Quotes | Token::Colon | Token::ArrayClose => {}
Token::Comma
| Token::CurlyClose
| Token::Quotes
| Token::Colon
| Token::ArrayClose => {}
}
}
value
}

fn process_object(iterator: &mut Peekable<Iter<Token>>) -> HashMap<String, Value> {
let mut is_key = true;
let mut current_key : Option<&str> = None;
let mut current_key: Option<&str> = None;
let mut value = HashMap::<String, Value>::new();
while let Some(token) = iterator.next() {
match token {
Token::CurlyOpen => {
if let Some(current_key) = current_key {
value.insert(current_key.to_string(), Value::Object(Self::process_object(iterator)));
value.insert(
current_key.to_string(),
Value::Object(Self::process_object(iterator)),
);
}
}
Token::CurlyClose => {
break;
}
Token::Quotes | Token::ArrayClose => {},
Token::Quotes | Token::ArrayClose => {}
Token::Colon => {
is_key = false;
}
Expand Down Expand Up @@ -104,7 +116,6 @@ impl JsonParser {

while let Some(token) = iterator.next() {
match token {

Token::CurlyOpen => {
internal_value.push(Value::Object(Self::process_object(iterator)));
}
Expand All @@ -119,10 +130,9 @@ impl JsonParser {
Token::Boolean(boolean) => internal_value.push(Value::Boolean(*boolean)),
Token::Null => internal_value.push(Value::Null),
Token::Comma | Token::CurlyClose | Token::Quotes | Token::Colon => {}

}
}

internal_value
}
}
}
23 changes: 14 additions & 9 deletions utils/sv2_serde_json/src/reader.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::{
collections::VecDeque,
io::{BufReader, Cursor, Read, Seek}, str::from_utf8,
io::{BufReader, Cursor, Read, Seek},
str::from_utf8,
};

pub struct JsonReader<T>
Expand All @@ -16,7 +17,10 @@ where
T: Read + Seek,
{
pub fn new(reader: BufReader<T>) -> Self {
JsonReader { reader, character_buffer: VecDeque::with_capacity(4) }
JsonReader {
reader,
character_buffer: VecDeque::with_capacity(4),
}
}
#[must_use]
pub fn from_bytes(bytes: &[u8]) -> JsonReader<Cursor<&[u8]>> {
Expand All @@ -27,33 +31,34 @@ where
}
}

impl <T> Iterator for JsonReader<T> where T: Read + Seek {

type Item = char;
impl<T> Iterator for JsonReader<T>
where
T: Read + Seek,
{
type Item = char;

#[allow(clippy::cast_possible_wrap)]
fn next(&mut self) -> Option<Self::Item> {
if !self.character_buffer.is_empty() {
return self.character_buffer.pop_front();
}

let mut utf8_buffer = [0,0,0,0];
let mut utf8_buffer = [0, 0, 0, 0];
let _ = self.reader.read(&mut utf8_buffer);
match from_utf8(&utf8_buffer) {
Ok(string) => {
self.character_buffer = string.chars().collect();
self.character_buffer.pop_front()
}
Err(error ) => {
Err(error) => {
let valid_bytes = error.valid_up_to();
let string = from_utf8(&utf8_buffer[..valid_bytes]).unwrap();
let remaining_bytes = 4 - valid_bytes;

let _ = self.reader.seek_relative(-(remaining_bytes as i64));
self.character_buffer = string.chars().collect();
self.character_buffer.pop_back()
self.character_buffer.pop_back()
}
}

}
}
54 changes: 34 additions & 20 deletions utils/sv2_serde_json/src/token.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
use std::{fs::File, io::{BufReader, Cursor, Read, Seek}, iter::Peekable};
use std::{
fs::File,
io::{BufReader, Cursor, Read, Seek},
iter::Peekable,
};

use crate::{reader::JsonReader, value::Number};


#[derive(Debug, Clone, PartialEq)]
pub enum Token {
CurlyOpen,
Expand All @@ -15,28 +18,42 @@ pub enum Token {
ArrayClose,
Comma,
Boolean(bool),
Null
Null,
}


pub struct Jsontokensizer<T> where T: Read + Seek {
pub struct Jsontokensizer<T>
where
T: Read + Seek,
{
tokens: Vec<Token>,
iterator: Peekable<JsonReader<T>>
iterator: Peekable<JsonReader<T>>,
}

impl<T> Jsontokensizer<T> where T: Read + Seek {
impl<T> Jsontokensizer<T>
where
T: Read + Seek,
{
pub fn new(reader: File) -> Jsontokensizer<File> {
let json_reader = JsonReader::<File>::new(BufReader::new(reader));
Jsontokensizer { tokens: vec![], iterator: json_reader.peekable() }
Jsontokensizer {
tokens: vec![],
iterator: json_reader.peekable(),
}
}

pub fn from_bytes<'a>(input: &'a [u8]) -> Jsontokensizer<Cursor<&'a [u8]>> {
let json_reader = JsonReader::<Cursor<&'a [u8]>>::from_bytes(input);
Jsontokensizer { tokens: Vec::with_capacity(input.len()), iterator: json_reader.peekable() }
Jsontokensizer {
tokens: Vec::with_capacity(input.len()),
iterator: json_reader.peekable(),
}
}
}

impl<T> Jsontokensizer<T> where T: Read + Seek {
impl<T> Jsontokensizer<T>
where
T: Read + Seek,
{
pub fn tokensize_json(&mut self) -> Result<&[Token], ()> {
while let Some(character) = self.iterator.peek() {
match *character {
Expand All @@ -57,24 +74,22 @@ impl<T> Jsontokensizer<T> where T: Read + Seek {
self.tokens.push(Token::Number(number));
}
't' => {
let _ =self.iterator.next();
let _ = self.iterator.next();

assert_eq!(Some('r'), self.iterator.next());
assert_eq!(Some('u'), self.iterator.next());
assert_eq!(Some('e'), self.iterator.next());
assert_eq!(Some('e'), self.iterator.next());
self.tokens.push(Token::Boolean(true));
}
'f' => {

let _ = self.iterator.next();
assert_eq!(Some('a'), self.iterator.next());

assert_eq!(Some('l'), self.iterator.next());
assert_eq!(Some('s'), self.iterator.next());

assert_eq!(Some('e'), self.iterator.next());
self.tokens.push(Token::Boolean(false));

}
'n' => {
let _ = self.iterator.next();
Expand Down Expand Up @@ -114,13 +129,12 @@ impl<T> Jsontokensizer<T> where T: Read + Seek {
} else {
self.iterator.next();
}
},
}
}
}
Ok(&self.tokens)
}


fn parse_string(&mut self) -> String {
let mut string_characters = Vec::<char>::new();

Expand All @@ -146,7 +160,7 @@ impl<T> Jsontokensizer<T> where T: Read + Seek {
while let Some(character) = self.iterator.peek() {
match character {
'-' => {
if is_epsilon_characters {
if is_epsilon_characters {
epsilon_characters.push('-');
} else {
number_characters.push('-');
Expand All @@ -157,7 +171,7 @@ impl<T> Jsontokensizer<T> where T: Read + Seek {
let _ = self.iterator.next();
}
digit @ '0'..='9' => {
if is_epsilon_characters {
if is_epsilon_characters {
epsilon_characters.push(*digit);
} else {
number_characters.push(*digit);
Expand Down Expand Up @@ -205,4 +219,4 @@ impl<T> Jsontokensizer<T> where T: Read + Seek {
))
}
}
}
}
Loading

0 comments on commit 742bcde

Please sign in to comment.