Skip to content

Commit

Permalink
Merge branch 'main' into darksky/move_compatibility_test
Browse files Browse the repository at this point in the history
  • Loading branch information
darkskygit authored Sep 26, 2023
2 parents ca63014 + ff89ad2 commit 69508e7
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 158 deletions.
10 changes: 2 additions & 8 deletions y-octo-node/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,7 @@ export class YArray {
get length(): number
get isEmpty(): boolean
get<T = unknown>(index: number): T
insert(index: number, value: unknown): void
setArray(index: number, array: YArray): void
setMap(index: number, map: YMap): void
setText(index: number, text: YText): void
insert(index: number, value: YArray | YMap | YText | boolean | number | string | Record<string, any> | null | undefined): void
remove(index: number, len: number): void
toJson(): JsArray
}
Expand All @@ -36,10 +33,7 @@ export class YMap {
get length(): number
get isEmpty(): boolean
get<T = unknown>(key: string): T
set(key: string, value: unknown): void
setArray(key: string, array: YArray): void
setMap(key: string, map: YMap): void
setText(key: string, text: YText): void
set(key: string, value: YArray | YMap | YText | boolean | number | string | Record<string, any> | null | undefined): void
remove(key: string): void
toJson(): object
}
Expand Down
132 changes: 58 additions & 74 deletions y-octo-node/src/array.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
use napi::{
bindgen_prelude::{Array as JsArray, Either4},
Env, JsUnknown, ValueType,
};
use napi::{bindgen_prelude::Array as JsArray, Env, JsUnknown, ValueType};
use y_octo::{Any, Array, Value};

use super::*;
Expand Down Expand Up @@ -36,53 +33,64 @@ impl YArray {
pub fn get(&self, env: Env, index: i64) -> Result<MixedYType> {
if let Some(value) = self.array.get(index as u64) {
match value {
Value::Any(any) => get_js_unknown_from_any(env, any).map(Either4::D),
Value::Array(array) => Ok(Either4::A(YArray::inner_new(array))),
Value::Map(map) => Ok(Either4::B(YMap::inner_new(map))),
Value::Text(text) => Ok(Either4::C(YText::inner_new(text))),
_ => env.get_null().map(|v| v.into_unknown()).map(Either4::D),
Value::Any(any) => get_js_unknown_from_any(env, any).map(MixedYType::D),
Value::Array(array) => Ok(MixedYType::A(YArray::inner_new(array))),
Value::Map(map) => Ok(MixedYType::B(YMap::inner_new(map))),
Value::Text(text) => Ok(MixedYType::C(YText::inner_new(text))),
_ => env.get_null().map(|v| v.into_unknown()).map(MixedYType::D),
}
.map_err(anyhow::Error::from)
} else {
Ok(Either4::D(env.get_null()?.into_unknown()))
Ok(MixedYType::D(env.get_null()?.into_unknown()))
}
}

#[napi]
pub fn insert(&mut self, index: i64, value: JsUnknown) -> Result<()> {
match value.get_type() {
Ok(value_type) => match value_type {
ValueType::Undefined | ValueType::Null => {
self.array.insert(index as u64, Any::Null).map_err(anyhow::Error::from)
}
ValueType::Boolean => {
if let Ok(boolean) = value.coerce_to_bool().and_then(|v| v.get_value()) {
self.array.insert(index as u64, boolean).map_err(anyhow::Error::from)
} else {
Err(anyhow::Error::msg("Failed to coerce value to boolean"))
#[napi(
ts_args_type = "index: number, value: YArray | YMap | YText | boolean | number | string | Record<string, any> \
| null | undefined"
)]
pub fn insert(&mut self, index: i64, value: MixedRefYType) -> Result<()> {
match value {
MixedRefYType::A(array) => self
.array
.insert(index as u64, array.array.clone())
.map_err(anyhow::Error::from),
MixedRefYType::B(map) => self
.array
.insert(index as u64, map.map.clone())
.map_err(anyhow::Error::from),
MixedRefYType::C(text) => self
.array
.insert(index as u64, text.text.clone())
.map_err(anyhow::Error::from),
MixedRefYType::D(unknown) => match unknown.get_type() {
Ok(value_type) => match value_type {
ValueType::Undefined | ValueType::Null => {
self.array.insert(index as u64, Any::Null).map_err(anyhow::Error::from)
}
}
ValueType::Number => {
if let Ok(number) = value.coerce_to_number().and_then(|v| v.get_double()) {
self.array.insert(index as u64, number).map_err(anyhow::Error::from)
} else {
Err(anyhow::Error::msg("Failed to coerce value to number"))
ValueType::Boolean => match unknown.coerce_to_bool().and_then(|v| v.get_value()) {
Ok(boolean) => self.array.insert(index as u64, boolean).map_err(anyhow::Error::from),
Err(e) => Err(anyhow::Error::new(e).context("Failed to coerce value to boolean")),
},
ValueType::Number => match unknown.coerce_to_number().and_then(|v| v.get_double()) {
Ok(number) => self.array.insert(index as u64, number).map_err(anyhow::Error::from),
Err(e) => Err(anyhow::Error::new(e).context("Failed to coerce value to number")),
},
ValueType::String => {
match unknown
.coerce_to_string()
.and_then(|v| v.into_utf8())
.and_then(|s| s.as_str().map(|s| s.to_string()))
{
Ok(string) => self.array.insert(index as u64, string).map_err(anyhow::Error::from),
Err(e) => Err(anyhow::Error::new(e).context("Failed to coerce value to string")),
}
}
}
ValueType::String => {
if let Ok(string) = value
.coerce_to_string()
.and_then(|v| v.into_utf8())
.and_then(|s| s.as_str().map(|s| s.to_string()))
ValueType::Object => match unknown
.coerce_to_object()
.and_then(|o| o.get_array_length().map(|l| (o, l)))
{
self.array.insert(index as u64, string).map_err(anyhow::Error::from)
} else {
Err(anyhow::Error::msg("Failed to coerce value to string"))
}
}
ValueType::Object => {
if let Ok(object) = value.coerce_to_object() {
if let Ok(length) = object.get_array_length() {
Ok((object, length)) => {
for i in 0..length {
if let Ok(any) = object.get_element::<JsUnknown>(i).and_then(get_any_from_js_unknown) {
self.array
Expand All @@ -91,43 +99,19 @@ impl YArray {
}
}
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")),
ValueType::Unknown => Err(anyhow::Error::msg("Unknown values are not supported")),
Err(e) => Err(anyhow::Error::new(e).context("Failed to coerce value to object")),
},
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")),
ValueType::Unknown => Err(anyhow::Error::msg("Unknown values are not supported")),
},
Err(e) => Err(anyhow::Error::from(e)),
},
Err(e) => Err(anyhow::Error::from(e)),
}
}

#[napi]
pub fn set_array(&mut self, index: i64, array: &YArray) -> Result<()> {
self.array.insert(index as u64, Value::Array(array.array.clone()))?;

Ok(())
}

#[napi]
pub fn set_map(&mut self, index: i64, map: &YMap) -> Result<()> {
self.array.insert(index as u64, Value::Map(map.map.clone()))?;

Ok(())
}

#[napi]
pub fn set_text(&mut self, index: i64, text: &YText) -> Result<()> {
self.array.insert(index as u64, Value::Text(text.text.clone()))?;

Ok(())
}

#[napi]
pub fn remove(&mut self, index: i64, len: i64) -> Result<()> {
self.array.remove(index as u64, len as u64).map_err(anyhow::Error::from)
Expand Down
3 changes: 2 additions & 1 deletion y-octo-node/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ pub use doc::Doc;
pub use map::YMap;
pub use text::YText;
use utils::{
get_any_from_js_object, get_any_from_js_unknown, get_js_unknown_from_any, get_js_unknown_from_value, MixedYType,
get_any_from_js_object, get_any_from_js_unknown, get_js_unknown_from_any, get_js_unknown_from_value, MixedRefYType,
MixedYType,
};
116 changes: 47 additions & 69 deletions y-octo-node/src/map.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use napi::{bindgen_prelude::Either4, Env, JsObject, JsUnknown, ValueType};
use napi::{Env, JsObject, ValueType};
use y_octo::{Any, Map, Value};

use super::*;
Expand Down Expand Up @@ -33,86 +33,64 @@ impl YMap {
pub fn get(&self, env: Env, key: String) -> Result<MixedYType> {
if let Some(value) = self.map.get(&key) {
match value {
Value::Any(any) => get_js_unknown_from_any(env, any).map(Either4::D),
Value::Array(array) => Ok(Either4::A(YArray::inner_new(array))),
Value::Map(map) => Ok(Either4::B(YMap::inner_new(map))),
Value::Text(text) => Ok(Either4::C(YText::inner_new(text))),
_ => env.get_null().map(|v| v.into_unknown()).map(Either4::D),
Value::Any(any) => get_js_unknown_from_any(env, any).map(MixedYType::D),
Value::Array(array) => Ok(MixedYType::A(YArray::inner_new(array))),
Value::Map(map) => Ok(MixedYType::B(YMap::inner_new(map))),
Value::Text(text) => Ok(MixedYType::C(YText::inner_new(text))),
_ => env.get_null().map(|v| v.into_unknown()).map(MixedYType::D),
}
.map_err(anyhow::Error::from)
} else {
Ok(Either4::D(env.get_null()?.into_unknown()))
Ok(MixedYType::D(env.get_null()?.into_unknown()))
}
}

#[napi]
pub fn set(&mut self, key: String, value: JsUnknown) -> Result<()> {
match value.get_type() {
Ok(value_type) => match value_type {
ValueType::Undefined | ValueType::Null => self.map.insert(key, Any::Null).map_err(anyhow::Error::from),
ValueType::Boolean => {
if let Ok(boolean) = value.coerce_to_bool().and_then(|v| v.get_value()) {
self.map.insert(key, boolean).map_err(anyhow::Error::from)
} else {
Err(anyhow::Error::msg("Failed to coerce value to boolean"))
}
}
ValueType::Number => {
if let Ok(number) = value.coerce_to_number().and_then(|v| v.get_double()) {
self.map.insert(key, number).map_err(anyhow::Error::from)
} else {
Err(anyhow::Error::msg("Failed to coerce value to number"))
#[napi(
ts_args_type = "key: string, value: YArray | YMap | YText | boolean | number | string | Record<string, any> | \
null | undefined"
)]
pub fn set(&mut self, key: String, value: MixedRefYType) -> Result<()> {
match value {
MixedRefYType::A(array) => self.map.insert(key, array.array.clone()).map_err(anyhow::Error::from),
MixedRefYType::B(map) => self.map.insert(key, map.map.clone()).map_err(anyhow::Error::from),
MixedRefYType::C(text) => self.map.insert(key, text.text.clone()).map_err(anyhow::Error::from),
MixedRefYType::D(unknown) => match unknown.get_type() {
Ok(value_type) => match value_type {
ValueType::Undefined | ValueType::Null => {
self.map.insert(key, Any::Null).map_err(anyhow::Error::from)
}
}
ValueType::String => {
if let Ok(string) = value
.coerce_to_string()
.and_then(|v| v.into_utf8())
.and_then(|s| s.as_str().map(|s| s.to_string()))
{
self.map.insert(key, string).map_err(anyhow::Error::from)
} else {
Err(anyhow::Error::msg("Failed to coerce value to string"))
ValueType::Boolean => match unknown.coerce_to_bool().and_then(|v| v.get_value()) {
Ok(boolean) => self.map.insert(key, boolean).map_err(anyhow::Error::from),
Err(e) => Err(anyhow::Error::from(e).context("Failed to coerce value to boolean")),
},
ValueType::Number => match unknown.coerce_to_number().and_then(|v| v.get_double()) {
Ok(number) => self.map.insert(key, number).map_err(anyhow::Error::from),
Err(e) => Err(anyhow::Error::from(e).context("Failed to coerce value to number")),
},
ValueType::String => {
match unknown
.coerce_to_string()
.and_then(|v| v.into_utf8())
.and_then(|s| s.as_str().map(|s| s.to_string()))
{
Ok(string) => self.map.insert(key, string).map_err(anyhow::Error::from),
Err(e) => Err(anyhow::Error::from(e).context("Failed to coerce value to string")),
}
}
}
ValueType::Object => {
if let Ok(object) = value.coerce_to_object() {
let any = get_any_from_js_object(object)?;
self.map.insert(key, Value::Any(any)).map_err(anyhow::Error::from)
} else {
Err(anyhow::Error::msg("Failed to coerce object 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")),
ValueType::Unknown => Err(anyhow::Error::msg("Unknown values are not supported")),
ValueType::Object => match unknown.coerce_to_object().and_then(get_any_from_js_object) {
Ok(any) => self.map.insert(key, Value::Any(any)).map_err(anyhow::Error::from),
Err(e) => Err(anyhow::Error::from(e).context("Failed to coerce value to object")),
},
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")),
ValueType::Unknown => Err(anyhow::Error::msg("Unknown values are not supported")),
},
Err(e) => Err(anyhow::Error::from(e)),
},
Err(e) => Err(anyhow::Error::from(e)),
}
}

#[napi]
pub fn set_array(&mut self, key: String, array: &YArray) -> Result<()> {
self.map.insert(key, Value::Array(array.array.clone()))?;

Ok(())
}

#[napi]
pub fn set_map(&mut self, key: String, map: &YMap) -> Result<()> {
self.map.insert(key, Value::Map(map.map.clone()))?;

Ok(())
}

#[napi]
pub fn set_text(&mut self, key: String, text: &YText) -> Result<()> {
self.map.insert(key, Value::Text(text.text.clone()))?;

Ok(())
}

#[napi]
pub fn remove(&mut self, key: String) {
self.map.remove(&key);
Expand Down
1 change: 1 addition & 0 deletions y-octo-node/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use y_octo::{Any, Value};
use super::*;

pub type MixedYType = Either4<YArray, YMap, YText, JsUnknown>;
pub type MixedRefYType<'a> = Either4<&'a YArray, &'a YMap, &'a YText, JsUnknown>;

pub fn get_js_unknown_from_any(env: Env, any: Any) -> Result<JsUnknown> {
match any {
Expand Down
2 changes: 1 addition & 1 deletion y-octo-node/tests/array.spec.mts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ test("array test", { concurrency: false }, async (t) => {
await t.test("sub array should can edit", () => {
let map = doc.getOrCreateMap("map");
let sub = doc.createArray();
map.setArray("sub", sub);
map.set("sub", sub);

sub.insert(0, true);
sub.insert(1, false);
Expand Down
8 changes: 4 additions & 4 deletions y-octo-node/tests/map.spec.mts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ test("map test", { concurrency: false }, async (t) => {
await t.test("map should can be nested", () => {
let map = doc.getOrCreateMap("map");
let sub = doc.createMap();
map.setMap("sub", sub);
map.set("sub", sub);

sub.set("a", true);
sub.set("b", false);
Expand All @@ -67,9 +67,9 @@ test("map test", { concurrency: false }, async (t) => {
let sub_map = doc.createMap();
let sub_text = doc.createText();

map.setArray("array", sub_array);
map.setMap("map", sub_map);
map.setText("text", sub_text);
map.set("array", sub_array);
map.set("map", sub_map);
map.set("text", sub_text);

sub_array.insert(0, true);
sub_array.insert(1, false);
Expand Down
2 changes: 1 addition & 1 deletion y-octo-node/tests/text.spec.mts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ test("text test", { concurrency: false }, async (t) => {
await t.test("sub text should can edit", () => {
let map = doc.getOrCreateMap("map");
let sub = doc.createText();
map.setText("sub", sub);
map.set("sub", sub);

sub.insert(0, "a");
sub.insert(1, "b");
Expand Down

0 comments on commit 69508e7

Please sign in to comment.