Skip to content

Commit

Permalink
feat: process array correctly
Browse files Browse the repository at this point in the history
  • Loading branch information
darkskygit committed Sep 16, 2023
1 parent d52b172 commit 2821906
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 6 deletions.
2 changes: 1 addition & 1 deletion y-octo-node/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ crate-type = ["cdylib"]
anyhow = "1"
napi = { version = "2", features = ["anyhow", "napi4"] }
napi-derive = "2"
y-octo = { path = "../y-octo" }
y-octo = { path = "../y-octo", features = ["large_refs"] }

[build-dependencies]
napi-build = "2"
23 changes: 20 additions & 3 deletions y-octo-node/src/array.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use napi::{bindgen_prelude::Array as JsArray, Env, JsUnknown, ValueType};
use y_octo::{Any, Array};
use y_octo::{Any, Array, Value};

use super::*;

Expand Down Expand Up @@ -74,7 +74,24 @@ impl YArray {
Err(anyhow::Error::msg("Failed to coerce value to string"))
}
}
ValueType::Object => Err(anyhow::Error::msg("Object values are not supported yet")),
ValueType::Object => {
if let Ok(object) = value.coerce_to_object() {
if let Ok(length) = object.get_array_length() {
for i in 0..length {
if let Ok(any) = object.get_element::<JsUnknown>(i).and_then(get_any_from_js_unknown) {
self.array
.insert(char_index as u64 + i as u64, Value::Any(any))
.map_err(|e| anyhow::Error::from(e))?;
}
}
Ok(())
} else {
Err(anyhow::Error::msg("Failed to coerce value to array"))
}
} else {
Err(anyhow::Error::msg("Failed to coerce value to array"))
}
}
ValueType::Symbol => Err(anyhow::Error::msg("Symbol values are not supported")),
ValueType::Function => Err(anyhow::Error::msg("Function values are not supported")),
ValueType::External => Err(anyhow::Error::msg("External values are not supported")),
Expand All @@ -93,7 +110,7 @@ impl YArray {

#[napi]
pub fn to_json(&self, env: Env) -> Result<JsArray> {
let mut js_array = env.create_array(self.array.len() as u32)?;
let mut js_array = env.create_array(0)?;
for value in self.array.iter() {
js_array.insert(get_js_unknown_from_value(env, value)?)?;
}
Expand Down
2 changes: 1 addition & 1 deletion y-octo-node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ pub use doc::Doc;
pub use map::YMap;
pub use text::YText;

use utils::{get_js_unknown_from_any, get_js_unknown_from_value};
use utils::{get_any_from_js_unknown, get_js_unknown_from_any, get_js_unknown_from_value};
55 changes: 54 additions & 1 deletion y-octo-node/src/utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::collections::HashMap;

use super::*;
use napi::{Env, JsUnknown, Result};
use napi::{Env, Error, JsUnknown, Result, Status, ValueType};
use y_octo::{Any, Value};

pub fn get_js_unknown_from_any(env: Env, any: Any) -> Result<JsUnknown> {
Expand Down Expand Up @@ -32,3 +34,54 @@ pub fn get_js_unknown_from_value(env: Env, value: Value) -> Result<JsUnknown> {
_ => env.get_null().map(|v| v.into_unknown()),
}
}

pub fn get_any_from_js_unknown(js_unknown: JsUnknown) -> Result<Any> {
match js_unknown.get_type()? {
ValueType::Undefined | ValueType::Null => Ok(Any::Null),
ValueType::Boolean => Ok(js_unknown.coerce_to_bool().and_then(|v| v.get_value())?.into()),
ValueType::Number => Ok(js_unknown
.coerce_to_number()
.and_then(|v| v.get_double())
.map(|v| v.into())?),
ValueType::String => Ok(js_unknown
.coerce_to_string()
.and_then(|v| v.into_utf8())
.and_then(|s| s.as_str().map(|s| s.to_string()))?
.into()),
ValueType::Object => {
if let Ok(object) = js_unknown.coerce_to_object() {
if let Ok(length) = object.get_array_length() {
let mut array = Vec::with_capacity(length as usize);
for i in 0..length as u32 {
if let Ok(value) = object.get_element::<JsUnknown>(i) {
array.push(get_any_from_js_unknown(value)?);
}
}
Ok(Any::Array(array))
} else {
let mut map = HashMap::new();
let keys = object.get_property_names()?;
if let Ok(length) = keys.get_array_length() {
for i in 0..length as u32 {
if let Ok((obj, key)) = keys.get_element::<JsUnknown>(i).and_then(|o| {
o.coerce_to_string().and_then(|obj| {
obj.clone()
.into_utf8()
.and_then(|s| s.as_str().map(|s| (obj, s.to_string())))
})
}) {
if let Ok(value) = object.get_property::<_, JsUnknown>(obj) {
map.insert(key, get_any_from_js_unknown(value)?);
}
}
}
}
Ok(Any::Object(map))
}
} else {
Err(Error::new(Status::InvalidArg, "Failed to coerce value to object"))
}
}
_ => Err(Error::new(Status::InvalidArg, "Failed to coerce value to any")),
}
}

0 comments on commit 2821906

Please sign in to comment.