From 48056e0941044a435d1a8fa65fadf2a08e9d81cb Mon Sep 17 00:00:00 2001 From: Diego Reis Date: Wed, 4 Jun 2025 09:20:32 -0300 Subject: [PATCH] bind/js: Refactor presentation modes to use an enum --- bindings/javascript/src/lib.rs | 219 ++++++++++++++++----------------- 1 file changed, 104 insertions(+), 115 deletions(-) diff --git a/bindings/javascript/src/lib.rs b/bindings/javascript/src/lib.rs index f587d6ccb..29c9e1b9f 100644 --- a/bindings/javascript/src/lib.rs +++ b/bindings/javascript/src/lib.rs @@ -202,6 +202,13 @@ impl Database { } } +#[derive(Debug, Clone)] +enum PresentationMode { + Raw, + Pluck, + None, +} + #[napi] #[derive(Clone)] pub struct Statement { @@ -216,8 +223,7 @@ pub struct Statement { pub source: String, database: Database, - raw: bool, - pluck: bool, + presentation_mode: PresentationMode, binded: bool, inner: Rc>, } @@ -229,9 +235,8 @@ impl Statement { inner: Rc::new(inner), database, source, - pluck: false, + presentation_mode: PresentationMode::None, binded: false, - raw: false, } } @@ -244,43 +249,44 @@ impl Statement { limbo_core::StepResult::Row => { let row = stmt.row().unwrap(); - if self.raw { - assert!(!self.pluck, "Cannot use raw mode with pluck mode"); + match self.presentation_mode { + PresentationMode::Raw => { + let mut raw_obj = env.create_array(row.len() as u32)?; + for (idx, value) in row.get_values().enumerate() { + let js_value = to_js_value(&env, value); - let mut raw_obj = env.create_array(row.len() as u32)?; - for (idx, value) in row.get_values().enumerate() { - let js_value = to_js_value(&env, value); + raw_obj.set(idx as u32, js_value)?; + } - raw_obj.set(idx as u32, js_value)?; + Ok(raw_obj.coerce_to_object()?.into_unknown()) } + PresentationMode::Pluck => { + let mut obj = env.create_object()?; - return Ok(raw_obj.coerce_to_object()?.into_unknown()); + let (idx, value) = + row.get_values().enumerate().next().ok_or(napi::Error::new( + napi::Status::GenericFailure, + "Pluck mode requires at least one column in the result", + ))?; + let key = stmt.get_column_name(idx); + let js_value = to_js_value(&env, value); + obj.set_named_property(&key, js_value)?; + + Ok(obj.into_unknown()) + } + PresentationMode::None => { + let mut obj = env.create_object()?; + + for (idx, value) in row.get_values().enumerate() { + let key = stmt.get_column_name(idx); + let js_value = to_js_value(&env, value); + + obj.set_named_property(&key, js_value)?; + } + + Ok(obj.into_unknown()) + } } - - let mut obj = env.create_object()?; - if self.pluck { - assert!(!self.raw, "Cannot use pluck mode with raw mode"); - - let (idx, value) = - row.get_values().enumerate().next().ok_or(napi::Error::new( - napi::Status::GenericFailure, - "Pluck mode requires at least one column in the result", - ))?; - let key = stmt.get_column_name(idx); - let js_value = to_js_value(&env, value); - obj.set_named_property(&key, js_value)?; - - return Ok(obj.into_unknown()); - } - - for (idx, value) in row.get_values().enumerate() { - let key = stmt.get_column_name(idx); - let js_value = to_js_value(&env, value); - - obj.set_named_property(&key, js_value)?; - } - - Ok(obj.into_unknown()) } limbo_core::StepResult::Done => Ok(env.get_undefined()?.into_unknown()), limbo_core::StepResult::IO => todo!(), @@ -305,20 +311,11 @@ impl Statement { args: Option>, ) -> napi::Result { self.check_and_bind(args)?; - if self.raw { - assert!(!self.pluck, "Cannot use raw mode with pluck mode"); - } - - if self.pluck { - assert!(!self.raw, "Cannot use pluck mode with raw mode"); - } - Ok(IteratorStatement { stmt: Rc::clone(&self.inner), database: self.database.clone(), env, - pluck: self.pluck, - raw: self.raw, + presentation_mode: self.presentation_mode.clone(), }) } @@ -342,42 +339,40 @@ impl Statement { let row = stmt.row().unwrap(); let mut obj = env.create_object()?; - if self.raw { - assert!(!self.pluck, "Cannot use raw mode with pluck mode"); - - let mut raw_array = env.create_array(row.len() as u32)?; - for (idx, value) in row.get_values().enumerate() { - let js_value = to_js_value(&env, value)?; - raw_array.set(idx as u32, js_value)?; + match self.presentation_mode { + PresentationMode::Raw => { + let mut raw_array = env.create_array(row.len() as u32)?; + for (idx, value) in row.get_values().enumerate() { + let js_value = to_js_value(&env, value)?; + raw_array.set(idx as u32, js_value)?; + } + results.set_element(index, raw_array.coerce_to_object()?)?; + index += 1; + continue; + } + PresentationMode::Pluck => { + let (idx, value) = + row.get_values().enumerate().next().ok_or(napi::Error::new( + napi::Status::GenericFailure, + "Pluck mode requires at least one column in the result", + ))?; + let key = stmt.get_column_name(idx); + let js_value = to_js_value(&env, value)?; + obj.set_named_property(&key, js_value)?; + results.set_element(index, obj)?; + index += 1; + continue; + } + PresentationMode::None => { + for (idx, value) in row.get_values().enumerate() { + let key = stmt.get_column_name(idx); + let js_value = to_js_value(&env, value); + obj.set_named_property(&key, js_value)?; + } + results.set_element(index, obj)?; + index += 1; } - results.set_element(index, raw_array.coerce_to_object()?)?; - index += 1; - continue; } - - if self.pluck { - assert!(!self.raw, "Cannot use pluck mode with raw mode"); - - let (idx, value) = - row.get_values().enumerate().next().ok_or(napi::Error::new( - napi::Status::GenericFailure, - "Pluck mode requires at least one column in the result", - ))?; - let key = stmt.get_column_name(idx); - let js_value = to_js_value(&env, value)?; - obj.set_named_property(&key, js_value)?; - results.set_element(index, obj)?; - index += 1; - continue; - } - - for (idx, value) in row.get_values().enumerate() { - let key = stmt.get_column_name(idx); - let js_value = to_js_value(&env, value); - obj.set_named_property(&key, js_value)?; - } - results.set_element(index, obj)?; - index += 1; } limbo_core::StepResult::Done => { break; @@ -400,11 +395,10 @@ impl Statement { #[napi] pub fn pluck(&mut self, pluck: Option) { if let Some(false) = pluck { - self.pluck = false; + self.presentation_mode = PresentationMode::None; } - self.raw = false; - self.pluck = true; + self.presentation_mode = PresentationMode::Pluck; } #[napi] @@ -415,11 +409,10 @@ impl Statement { #[napi] pub fn raw(&mut self, raw: Option) { if let Some(false) = raw { - self.raw = false; + self.presentation_mode = PresentationMode::None; } - self.pluck = false; - self.raw = true; + self.presentation_mode = PresentationMode::Raw; } #[napi] @@ -466,8 +459,7 @@ pub struct IteratorStatement { stmt: Rc>, database: Database, env: Env, - pluck: bool, - raw: bool, + presentation_mode: PresentationMode, } impl Generator for IteratorStatement { @@ -485,41 +477,38 @@ impl Generator for IteratorStatement { let row = stmt.row().unwrap(); let mut js_row = self.env.create_object().ok()?; - if self.raw { - assert!(!self.pluck, "Cannot use raw mode with pluck mode"); + match self.presentation_mode { + PresentationMode::Raw => { + let mut raw_array = self.env.create_array(row.len() as u32).ok()?; + for (idx, value) in row.get_values().enumerate() { + let js_value = to_js_value(&self.env, value); + raw_array.set(idx as u32, js_value).ok()?; + } - let mut raw_array = self.env.create_array(row.len() as u32).ok()?; - for (idx, value) in row.get_values().enumerate() { - let js_value = to_js_value(&self.env, value); - raw_array.set(idx as u32, js_value).ok()?; + raw_array.coerce_to_object().ok() } + PresentationMode::Pluck => { + let (idx, value) = row.get_values().enumerate().next()?; + let key = stmt.get_column_name(idx); + let js_value = to_js_value(&self.env, value); + js_row.set_named_property(&key, js_value).ok()?; + Some(js_row) + } + PresentationMode::None => { + for (idx, value) in row.get_values().enumerate() { + let key = stmt.get_column_name(idx); + let js_value = to_js_value(&self.env, value); + js_row.set_named_property(&key, js_value).ok()?; + } - // TODO: fix this unwrap - return Some(raw_array.coerce_to_object().unwrap()); + Some(js_row) + } } - - if self.pluck { - assert!(!self.raw, "Cannot use pluck mode with raw mode"); - - let (idx, value) = row.get_values().enumerate().next()?; - let key = stmt.get_column_name(idx); - let js_value = to_js_value(&self.env, value); - js_row.set_named_property(&key, js_value).ok()?; - return Some(js_row); - } - - for (idx, value) in row.get_values().enumerate() { - let key = stmt.get_column_name(idx); - let js_value = to_js_value(&self.env, value); - js_row.set_named_property(&key, js_value).ok()?; - } - - Some(js_row) } limbo_core::StepResult::Done => None, limbo_core::StepResult::IO => { self.database.io.run_once().ok()?; - None // clearly it's incorrect it should return to user + None // clearly it's incorrect, it should return to user } limbo_core::StepResult::Interrupt | limbo_core::StepResult::Busy => None, }