ZIm/crates/sqlez/src/bindable.rs
Nathan Sobo 6fca1d2b0b
Eliminate GPUI View, ViewContext, and WindowContext types (#22632)
There's still a bit more work to do on this, but this PR is compiling
(with warnings) after eliminating the key types. When the tasks below
are complete, this will be the new narrative for GPUI:

- `Entity<T>` - This replaces `View<T>`/`Model<T>`. It represents a unit
of state, and if `T` implements `Render`, then `Entity<T>` implements
`Element`.
- `&mut App` This replaces `AppContext` and represents the app.
- `&mut Context<T>` This replaces `ModelContext` and derefs to `App`. It
is provided by the framework when updating an entity.
- `&mut Window` Broken out of `&mut WindowContext` which no longer
exists. Every method that once took `&mut WindowContext` now takes `&mut
Window, &mut App` and every method that took `&mut ViewContext<T>` now
takes `&mut Window, &mut Context<T>`

Not pictured here are the two other failed attempts. It's been quite a
month!

Tasks:

- [x] Remove `View`, `ViewContext`, `WindowContext` and thread through
`Window`
- [x] [@cole-miller @mikayla-maki] Redraw window when entities change
- [x] [@cole-miller @mikayla-maki] Get examples and Zed running
- [x] [@cole-miller @mikayla-maki] Fix Zed rendering
- [x] [@mikayla-maki] Fix todo! macros and comments
- [x] Fix a bug where the editor would not be redrawn because of view
caching
- [x] remove publicness window.notify() and replace with
`AppContext::notify`
- [x] remove `observe_new_window_models`, replace with
`observe_new_models` with an optional window
- [x] Fix a bug where the project panel would not be redrawn because of
the wrong refresh() call being used
- [x] Fix the tests
- [x] Fix warnings by eliminating `Window` params or using `_`
- [x] Fix conflicts
- [x] Simplify generic code where possible
- [x] Rename types
- [ ] Update docs

### issues post merge

- [x] Issues switching between normal and insert mode
- [x] Assistant re-rendering failure
- [x] Vim test failures
- [x] Mac build issue



Release Notes:

- N/A

---------

Co-authored-by: Antonio Scandurra <me@as-cii.com>
Co-authored-by: Cole Miller <cole@zed.dev>
Co-authored-by: Mikayla <mikayla@zed.dev>
Co-authored-by: Joseph <joseph@zed.dev>
Co-authored-by: max <max@zed.dev>
Co-authored-by: Michael Sloan <michael@zed.dev>
Co-authored-by: Mikayla Maki <mikaylamaki@Mikaylas-MacBook-Pro.local>
Co-authored-by: Mikayla <mikayla.c.maki@gmail.com>
Co-authored-by: joão <joao@zed.dev>
2025-01-26 03:02:45 +00:00

457 lines
13 KiB
Rust

use std::{
path::{Path, PathBuf},
sync::Arc,
};
use anyhow::{Context as _, Result};
use util::paths::PathExt;
use crate::statement::{SqlType, Statement};
pub trait StaticColumnCount {
fn column_count() -> usize {
1
}
}
pub trait Bind {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32>;
}
pub trait Column: Sized {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)>;
}
impl StaticColumnCount for bool {}
impl Bind for bool {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
statement
.bind(&self.then_some(1).unwrap_or(0), start_index)
.with_context(|| format!("Failed to bind bool at index {start_index}"))
}
}
impl Column for bool {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
i32::column(statement, start_index)
.map(|(i, next_index)| (i != 0, next_index))
.with_context(|| format!("Failed to read bool at index {start_index}"))
}
}
impl StaticColumnCount for &[u8] {}
impl Bind for &[u8] {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
statement
.bind_blob(start_index, self)
.with_context(|| format!("Failed to bind &[u8] at index {start_index}"))?;
Ok(start_index + 1)
}
}
impl<const C: usize> StaticColumnCount for &[u8; C] {}
impl<const C: usize> Bind for &[u8; C] {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
statement
.bind_blob(start_index, self.as_slice())
.with_context(|| format!("Failed to bind &[u8; C] at index {start_index}"))?;
Ok(start_index + 1)
}
}
impl<const C: usize> Column for [u8; C] {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let bytes_slice = statement.column_blob(start_index)?;
let array = bytes_slice.try_into()?;
Ok((array, start_index + 1))
}
}
impl StaticColumnCount for Vec<u8> {}
impl Bind for Vec<u8> {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
statement
.bind_blob(start_index, self)
.with_context(|| format!("Failed to bind Vec<u8> at index {start_index}"))?;
Ok(start_index + 1)
}
}
impl Column for Vec<u8> {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let result = statement
.column_blob(start_index)
.with_context(|| format!("Failed to read Vec<u8> at index {start_index}"))?;
Ok((Vec::from(result), start_index + 1))
}
}
impl StaticColumnCount for f64 {}
impl Bind for f64 {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
statement
.bind_double(start_index, *self)
.with_context(|| format!("Failed to bind f64 at index {start_index}"))?;
Ok(start_index + 1)
}
}
impl Column for f64 {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let result = statement
.column_double(start_index)
.with_context(|| format!("Failed to parse f64 at index {start_index}"))?;
Ok((result, start_index + 1))
}
}
impl StaticColumnCount for f32 {}
impl Bind for f32 {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
statement
.bind_double(start_index, *self as f64)
.with_context(|| format!("Failed to bind f64 at index {start_index}"))?;
Ok(start_index + 1)
}
}
impl Column for f32 {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let result = statement
.column_double(start_index)
.with_context(|| format!("Failed to parse f32 at index {start_index}"))?
as f32;
Ok((result, start_index + 1))
}
}
impl StaticColumnCount for i32 {}
impl Bind for i32 {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
statement
.bind_int(start_index, *self)
.with_context(|| format!("Failed to bind i32 at index {start_index}"))?;
Ok(start_index + 1)
}
}
impl Column for i32 {
fn column<'a>(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let result = statement.column_int(start_index)?;
Ok((result, start_index + 1))
}
}
impl StaticColumnCount for i64 {}
impl Bind for i64 {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
statement
.bind_int64(start_index, *self)
.with_context(|| format!("Failed to bind i64 at index {start_index}"))?;
Ok(start_index + 1)
}
}
impl Column for i64 {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let result = statement.column_int64(start_index)?;
Ok((result, start_index + 1))
}
}
impl StaticColumnCount for u64 {}
impl Bind for u64 {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
statement
.bind_int64(start_index, (*self) as i64)
.with_context(|| format!("Failed to bind i64 at index {start_index}"))?;
Ok(start_index + 1)
}
}
impl Column for u64 {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let result = statement.column_int64(start_index)? as u64;
Ok((result, start_index + 1))
}
}
impl StaticColumnCount for u32 {}
impl Bind for u32 {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
(*self as i64)
.bind(statement, start_index)
.with_context(|| format!("Failed to bind usize at index {start_index}"))
}
}
impl Column for u32 {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let result = statement.column_int64(start_index)?;
Ok((result as u32, start_index + 1))
}
}
impl StaticColumnCount for u16 {}
impl Bind for u16 {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
(*self as i64)
.bind(statement, start_index)
.with_context(|| format!("Failed to bind usize at index {start_index}"))
}
}
impl Column for u16 {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let result = statement.column_int64(start_index)?;
Ok((result as u16, start_index + 1))
}
}
impl StaticColumnCount for usize {}
impl Bind for usize {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
(*self as i64)
.bind(statement, start_index)
.with_context(|| format!("Failed to bind usize at index {start_index}"))
}
}
impl Column for usize {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let result = statement.column_int64(start_index)?;
Ok((result as usize, start_index + 1))
}
}
impl StaticColumnCount for &str {}
impl Bind for &str {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
statement.bind_text(start_index, self)?;
Ok(start_index + 1)
}
}
impl StaticColumnCount for Arc<str> {}
impl Bind for Arc<str> {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
statement.bind_text(start_index, self.as_ref())?;
Ok(start_index + 1)
}
}
impl StaticColumnCount for String {}
impl Bind for String {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
statement.bind_text(start_index, self)?;
Ok(start_index + 1)
}
}
impl Column for Arc<str> {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let result = statement.column_text(start_index)?;
Ok((Arc::from(result), start_index + 1))
}
}
impl Column for String {
fn column<'a>(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let result = statement.column_text(start_index)?;
Ok((result.to_owned(), start_index + 1))
}
}
impl<T: StaticColumnCount> StaticColumnCount for Option<T> {
fn column_count() -> usize {
T::column_count()
}
}
impl<T: Bind + StaticColumnCount> Bind for Option<T> {
fn bind(&self, statement: &Statement, mut start_index: i32) -> Result<i32> {
if let Some(this) = self {
this.bind(statement, start_index)
} else {
for _ in 0..T::column_count() {
statement.bind_null(start_index)?;
start_index += 1;
}
Ok(start_index)
}
}
}
impl<T: Column + StaticColumnCount> Column for Option<T> {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
if let SqlType::Null = statement.column_type(start_index)? {
Ok((None, start_index + T::column_count() as i32))
} else {
T::column(statement, start_index).map(|(result, next_index)| (Some(result), next_index))
}
}
}
impl<T: StaticColumnCount, const COUNT: usize> StaticColumnCount for [T; COUNT] {
fn column_count() -> usize {
T::column_count() * COUNT
}
}
impl<T: Bind, const COUNT: usize> Bind for [T; COUNT] {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
let mut current_index = start_index;
for binding in self {
current_index = binding.bind(statement, current_index)?
}
Ok(current_index)
}
}
impl StaticColumnCount for &Path {}
impl Bind for &Path {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
self.as_os_str()
.as_encoded_bytes()
.bind(statement, start_index)
}
}
impl StaticColumnCount for Arc<Path> {}
impl Bind for Arc<Path> {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
self.as_ref().bind(statement, start_index)
}
}
impl StaticColumnCount for PathBuf {}
impl Bind for PathBuf {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
(self.as_ref() as &Path).bind(statement, start_index)
}
}
impl Column for PathBuf {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let blob = statement.column_blob(start_index)?;
PathBuf::try_from_bytes(blob).map(|path| (path, start_index + 1))
}
}
impl StaticColumnCount for uuid::Uuid {
fn column_count() -> usize {
1
}
}
impl Bind for uuid::Uuid {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
self.as_bytes().bind(statement, start_index)
}
}
impl Column for uuid::Uuid {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let (bytes, next_index) = Column::column(statement, start_index)?;
Ok((uuid::Uuid::from_bytes(bytes), next_index))
}
}
impl StaticColumnCount for () {
fn column_count() -> usize {
0
}
}
/// Unit impls do nothing. This simplifies query macros
impl Bind for () {
fn bind(&self, _statement: &Statement, start_index: i32) -> Result<i32> {
Ok(start_index)
}
}
impl Column for () {
fn column(_statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
Ok(((), start_index))
}
}
macro_rules! impl_tuple_row_traits {
( $($local:ident: $type:ident),+ ) => {
impl<$($type: StaticColumnCount),+> StaticColumnCount for ($($type,)+) {
fn column_count() -> usize {
let mut count = 0;
$(count += $type::column_count();)+
count
}
}
impl<$($type: Bind),+> Bind for ($($type,)+) {
fn bind(&self, statement: &Statement, start_index: i32) -> Result<i32> {
let mut next_index = start_index;
let ($($local,)+) = self;
$(next_index = $local.bind(statement, next_index)?;)+
Ok(next_index)
}
}
impl<$($type: Column),+> Column for ($($type,)+) {
fn column(statement: &mut Statement, start_index: i32) -> Result<(Self, i32)> {
let mut next_index = start_index;
Ok((
(
$({
let value;
(value, next_index) = $type::column(statement, next_index)?;
value
},)+
),
next_index,
))
}
}
}
}
impl_tuple_row_traits!(t1: T1, t2: T2);
impl_tuple_row_traits!(t1: T1, t2: T2, t3: T3);
impl_tuple_row_traits!(t1: T1, t2: T2, t3: T3, t4: T4);
impl_tuple_row_traits!(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5);
impl_tuple_row_traits!(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6);
impl_tuple_row_traits!(t1: T1, t2: T2, t3: T3, t4: T4, t5: T5, t6: T6, t7: T7);
impl_tuple_row_traits!(
t1: T1,
t2: T2,
t3: T3,
t4: T4,
t5: T5,
t6: T6,
t7: T7,
t8: T8
);
impl_tuple_row_traits!(
t1: T1,
t2: T2,
t3: T3,
t4: T4,
t5: T5,
t6: T6,
t7: T7,
t8: T8,
t9: T9
);
impl_tuple_row_traits!(
t1: T1,
t2: T2,
t3: T3,
t4: T4,
t5: T5,
t6: T6,
t7: T7,
t8: T8,
t9: T9,
t10: T10
);