Skip to content

Commit

Permalink
Added some examples
Browse files Browse the repository at this point in the history
  • Loading branch information
kaleidawave committed Dec 5, 2023
1 parent e539097 commit f436ab7
Show file tree
Hide file tree
Showing 3 changed files with 308 additions and 3 deletions.
145 changes: 145 additions & 0 deletions examples/to_object.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
use std::collections::HashMap;

use simple_json_parser::{parse, JSONKey, RootJSONValue};

fn main() {
let content = r#"{
"name": "ezno",
"version": "0.0.14",
"description": "A JavaScript compiler and TypeScript checker written in Rust with a focus on static analysis and runtime performance",
"license": "MIT",
"repository": "https://github.com/kaleidawave/ezno",
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"type": "module",
"exports": {
".": {
"import": "./dist/index.mjs"
},
"./initialised": {
"import": "./dist/initialised.mjs"
}
},
"scripts": {
"clean": "rmdir dist && rmdir build",
"build": "cargo build --lib --target wasm32-unknown-unknown && npm run bind && npm run build-js",
"build-release": "cargo build --lib --release --target wasm32-unknown-unknown && npm run bind-release && npm run build-js",
"bind": "wasm-bindgen --out-dir build --target web ../../target/wasm32-unknown-unknown/debug/ezno_lib.wasm",
"bind-release": "wasm-bindgen --out-dir build --target web ../../target/wasm32-unknown-unknown/release/ezno_lib.wasm",
"build-js": "unbuild && cp ./build/ezno_lib_bg.wasm dist/shared && cp src/cli_node.cjs dist/cli.cjs",
"test": "npm run build && npm run run-tests",
"run-tests": "node test.mjs && deno run -A test.mjs"
},
"keywords": [
"typescript",
"checker",
"type-checker",
"compiler"
],
"files": [
"dist"
],
"bin": {
"ezno": "./dist/cli.mjs"
},
"author": {
"name": "Ben",
"email": "kaleidawave@gmail.com",
"url": "https://kaleidawave.github.io/"
},
"funding": {
"type": "individual",
/*
multiline comment
*/
"url": "https://github.com/sponsors/kaleidawave"
},
"build": {
"failOnWarn": false,
"entries": [
{
"builder": "rollup",
"input": "./src/index"
},
{
"builder": "rollup",
"input": "./src/initialised"
},
{
"builder": "rollup",
"input": "./src/cli"
}
],
// some comment
"rollup": {
"commonjs": true,
"esbuild": {
"target": "esnext"
}
}
},
"devDependencies": {
"unbuild": "^1.1.2"
}
}"#;

pub type Object = HashMap<String, Value>;

#[derive(Debug)]
pub enum Value {
Object(Object),
String(String),
Number(String),
Boolean(bool),
Null,
}

impl Value {
pub fn new_empty_object() -> Self {
Self::Object(HashMap::new())
}

pub fn set<'a>(&'a mut self, keys: &'a [JSONKey<'a>], value: RootJSONValue<'a>) {
if let Value::Object(ref mut obj) = self {
if let [last] = keys {
let name = match last {
JSONKey::Slice(s) => s.to_string(),
JSONKey::Index(i) => i.to_string(),
};
let value = match value {
RootJSONValue::String(s) => Value::String(s.to_string()),
RootJSONValue::Number(n) => Value::Number(n.to_string()),
RootJSONValue::True => Value::Boolean(true),
RootJSONValue::False => Value::Boolean(false),
RootJSONValue::Null => Value::Null,
};
let existing = obj.insert(name, value);
debug_assert!(existing.is_none());
} else if let [first, others @ ..] = keys {
let name = match first {
JSONKey::Slice(s) => s.to_string(),
JSONKey::Index(i) => i.to_string(),
};
obj.entry(name)
.or_insert_with(Value::new_empty_object)
.set(others, value);
} else {
unreachable!("empty keys")
}
} else {
unreachable!()
}
}
}

let mut root = Value::new_empty_object();

let result = parse(content, |keys, value| root.set(keys, value));

match result {
Ok(()) => {
eprintln!("Object:\n{:#?}", root);
}
Err((idx, err)) => eprintln!("{err:?} @ {idx}"),
}
}
157 changes: 157 additions & 0 deletions examples/to_object_unsafe.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
//! Uses iterations rather than recursion to build a object map. Unfortunately at the cost of using `unsafe`
use std::collections::HashMap;

use simple_json_parser::{parse, JSONKey, RootJSONValue};

fn main() {
let content = r#"{
"name": "ezno",
"version": "0.0.14",
"description": "A JavaScript compiler and TypeScript checker written in Rust with a focus on static analysis and runtime performance",
"license": "MIT",
"repository": "https://github.com/kaleidawave/ezno",
"main": "./dist/index.mjs",
"module": "./dist/index.mjs",
"type": "module",
"exports": {
".": {
"import": "./dist/index.mjs"
},
"./initialised": {
"import": "./dist/initialised.mjs"
}
},
"scripts": {
"clean": "rmdir dist && rmdir build",
"build": "cargo build --lib --target wasm32-unknown-unknown && npm run bind && npm run build-js",
"build-release": "cargo build --lib --release --target wasm32-unknown-unknown && npm run bind-release && npm run build-js",
"bind": "wasm-bindgen --out-dir build --target web ../../target/wasm32-unknown-unknown/debug/ezno_lib.wasm",
"bind-release": "wasm-bindgen --out-dir build --target web ../../target/wasm32-unknown-unknown/release/ezno_lib.wasm",
"build-js": "unbuild && cp ./build/ezno_lib_bg.wasm dist/shared && cp src/cli_node.cjs dist/cli.cjs",
"test": "npm run build && npm run run-tests",
"run-tests": "node test.mjs && deno run -A test.mjs"
},
"keywords": [
"typescript",
"checker",
"type-checker",
"compiler"
],
"files": [
"dist"
],
"bin": {
"ezno": "./dist/cli.mjs"
},
"author": {
"name": "Ben",
"email": "kaleidawave@gmail.com",
"url": "https://kaleidawave.github.io/"
},
"funding": {
"type": "individual",
/*
multiline comment
*/
"url": "https://github.com/sponsors/kaleidawave"
},
"build": {
"failOnWarn": false,
"entries": [
{
"builder": "rollup",
"input": "./src/index"
},
{
"builder": "rollup",
"input": "./src/initialised"
},
{
"builder": "rollup",
"input": "./src/cli"
}
],
// some comment
"rollup": {
"commonjs": true,
"esbuild": {
"target": "esnext"
}
}
},
"devDependencies": {
"unbuild": "^1.1.2"
}
}"#;

pub type Object = HashMap<String, Value>;

#[derive(Debug)]
pub enum Value {
Object(Object),
String(String),
Number(String),
Boolean(bool),
Null,
}

impl Value {
pub fn new_empty_object() -> Self {
Self::Object(HashMap::new())
}
}

let mut root = Object::new();

let result = parse(content, |keys, value| {
let [path @ .., end] = keys else {
unreachable!("empty key change")
};
let pointer = &mut root;

let mut to_add_to: *mut Object = pointer;

for key in path {
let name = match key {
JSONKey::Slice(s) => s.to_string(),
JSONKey::Index(i) => i.to_string(),
};
if let Some(Value::Object(ref mut obj)) =
unsafe { (to_add_to.as_mut().unwrap()).get_mut(&name) }
{
to_add_to = obj;
} else {
let value = unsafe {
(to_add_to.as_mut().unwrap())
.entry(name)
.or_insert_with(Value::new_empty_object)
};
if let Value::Object(ref mut obj) = value {
to_add_to = obj;
}
}
}
let name = match end {
JSONKey::Slice(s) => s.to_string(),
JSONKey::Index(i) => i.to_string(),
};
let value = match value {
RootJSONValue::String(s) => Value::String(s.to_string()),
RootJSONValue::Number(n) => Value::Number(n.to_string()),
RootJSONValue::True => Value::Boolean(true),
RootJSONValue::False => Value::Boolean(false),
RootJSONValue::Null => Value::Null,
};
unsafe {
(to_add_to.as_mut().unwrap()).insert(name, value);
}
});

match result {
Ok(()) => {
eprintln!("Object:\n{:#?}", root);
}
Err((idx, err)) => eprintln!("{err:?} @ {idx}"),
}
}
9 changes: 6 additions & 3 deletions lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub enum JSONParseError {

pub fn parse<'a>(
on: &'a str,
cb: impl for<'b> Fn(&'b [JSONKey<'a>], RootJSONValue<'a>),
mut cb: impl for<'b> FnMut(&'b [JSONKey<'a>], RootJSONValue<'a>),
) -> Result<(), (usize, JSONParseError)> {
let chars = on.char_indices();

Expand All @@ -39,6 +39,7 @@ pub fn parse<'a>(
start: usize,
multiline: bool,
last_was_asterisk: bool,
hash: bool,
},
ExpectingValue,
None,
Expand Down Expand Up @@ -119,6 +120,7 @@ pub fn parse<'a>(
State::Comment {
ref mut last_was_asterisk,
ref mut multiline,
hash,
start,
} => {
if char == '\n' && !*multiline {
Expand All @@ -127,7 +129,7 @@ pub fn parse<'a>(
} else {
state = State::InObject
}
} else if char == '*' && start + 1 == idx {
} else if char == '*' && start + 1 == idx && !hash {
*multiline = true
} else if *multiline {
if *last_was_asterisk && char == '/' {
Expand All @@ -152,10 +154,11 @@ pub fn parse<'a>(
start: idx + '"'.len_utf8(),
escaped: false,
},
'/' => State::Comment {
c @ ('/' | '#') => State::Comment {
last_was_asterisk: false,
start: idx,
multiline: false,
hash: c == '#',
},
'0'..='9' | '-' => State::NumberValue { start: idx },
't' | 'f' | 'n' => State::TrueFalseNull { start: idx },
Expand Down

0 comments on commit f436ab7

Please sign in to comment.